From 3f20055cd672d7175fb45293b14d74b26f55d6c5 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Thu, 24 Jun 2021 22:15:46 -0600 Subject: [PATCH] proper support for static class methods --- src/Convert/Package.hs | 17 ++++++- src/Convert/Traverse.hs | 10 ++-- src/Language/SystemVerilog/AST/Description.hs | 26 ++++++++-- src/Language/SystemVerilog/Parser/Parse.y | 51 ++++++++++++++----- test/basic/subroutine.sv | 3 +- 5 files changed, 85 insertions(+), 22 deletions(-) diff --git a/src/Convert/Package.hs b/src/Convert/Package.hs index 05e2890..e7f13a3 100644 --- a/src/Convert/Package.hs +++ b/src/Convert/Package.hs @@ -77,7 +77,22 @@ collectPackageM (PackageItem item) = collectPackageM (Package _ name items) = tell (Map.singleton name (Map.empty, items), Map.empty, []) collectPackageM (Class _ name decls items) = - tell (Map.empty, Map.singleton name (decls, items), []) + tell (Map.empty, Map.singleton name (decls, map unpackClassItem items), []) + where + unpackClassItem :: ClassItem -> PackageItem + unpackClassItem (item @ (_, Task{})) = checkTF item + unpackClassItem (item @ (_, Function{})) = checkTF item + unpackClassItem item = checkNonTF item + checkTF :: ClassItem -> PackageItem + checkTF (QStatic, item) = item + checkTF (_, item) = + error $ "unsupported declaration of non-static method " ++ itemName + where [itemName] = piNames item + checkNonTF :: ClassItem -> PackageItem + checkNonTF (QNone, item) = item + checkNonTF (qualifier, _) = + error $ "unexpected qualifier " ++ show qualifier + ++ " on a class item which is not a task or a function" collectPackageM _ = return () -- elaborate all packages and their usages diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index 667bd15..25b19e8 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -165,11 +165,13 @@ traverseModuleItemsM mapper (Class lifetime name decls items) = do declsWrapped' <- mapM (traverseNestedModuleItemsM mapper) declsWrapped let decls' = map (\(MIPackageItem (Decl decl)) -> decl) $ concatMap breakGenerate declsWrapped' - let itemsWrapped = map MIPackageItem items - itemsWrapped' <- mapM (traverseNestedModuleItemsM mapper) itemsWrapped - let items' = map (\(MIPackageItem item) -> item) $ - concatMap breakGenerate itemsWrapped' + items' <- fmap concat $ mapM indirect items return $ Class lifetime name decls' items' + where + indirect (qualifier, item) = + fmap (map (unwrap qualifier) . breakGenerate) $ + traverseNestedModuleItemsM mapper (MIPackageItem item) + unwrap qualifier = \(MIPackageItem item) -> (qualifier, item) traverseModuleItems :: Mapper ModuleItem -> Mapper Description traverseModuleItems = unmonad traverseModuleItemsM diff --git a/src/Language/SystemVerilog/AST/Description.hs b/src/Language/SystemVerilog/AST/Description.hs index 05fb4d7..45ea28c 100644 --- a/src/Language/SystemVerilog/AST/Description.hs +++ b/src/Language/SystemVerilog/AST/Description.hs @@ -10,6 +10,8 @@ module Language.SystemVerilog.AST.Description , PackageItem (..) , PartKW (..) , Lifetime (..) + , Qualifier (..) + , ClassItem ) where import Text.Printf (printf) @@ -26,7 +28,7 @@ data Description = Part [Attr] Bool PartKW Lifetime Identifier [Identifier] [ModuleItem] | PackageItem PackageItem | Package Lifetime Identifier [PackageItem] - | Class Lifetime Identifier [Decl] [PackageItem] + | Class Lifetime Identifier [Decl] [ClassItem] deriving Eq instance Show Description where @@ -54,8 +56,8 @@ instance Show Description where printf "class %s%s;\n%s\nendclass" (showPad lifetime) name bodyStr where - bodyStr = indent $ unlines' $ map show items' - items' = (map Decl decls) ++ items + bodyStr = indent $ unlines' $ map showClassItem items' + items' = (map (\decl -> (QNone, Decl decl)) decls) ++ items show (PackageItem i) = show i data PackageItem @@ -102,3 +104,21 @@ instance Show Lifetime where show Static = "static" show Automatic = "automatic" show Inherit = "" + +type ClassItem = (Qualifier, PackageItem) + +showClassItem :: ClassItem -> String +showClassItem (qualifier, item) = showPad qualifier ++ show item + +data Qualifier + = QNone + | QStatic + | QLocal + | QProtected + deriving Eq + +instance Show Qualifier where + show QNone = "" + show QStatic = "static" + show QLocal = "local" + show QProtected = "protected" diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index f508790..f7c85d8 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -13,6 +13,7 @@ -} { {-# LANGUAGE BlockArguments #-} +{-# LANGUAGE TupleSections #-} module Language.SystemVerilog.Parser.Parse (parse) where import Control.Monad.Except @@ -557,7 +558,7 @@ InterfaceKW :: { PartKW } PackageDeclaration :: { Description } : "package" Lifetime Identifier ";" PackageItems endpackage StrTag {% checkTag $3 $7 $ Package $2 $3 $5 } - | "class" Lifetime Identifier PIParams ";" PackageItems endclass StrTag {% checkTag $3 $8 $ Class $2 $3 $4 $6 } + | "class" Lifetime Identifier PIParams ";" ClassItems endclass StrTag {% checkTag $3 $8 $ Class $2 $3 $4 $6 } StrTag :: { Identifier } : {- empty -} { "" } @@ -643,7 +644,7 @@ DeclToken :: { DeclToken } | "." Identifier {% posInject \p -> DTDot p $2 } | PortBindings {% posInject \p -> DTInstance p $1 } | Signing {% posInject \p -> DTSigning p $1 } - | ExplicitLifetime {% posInject \p -> DTLifetime p $1 } + | "automatic" {% posInject \p -> DTLifetime p Automatic } | "const" PartialType {% posInject \p -> DTType p $2 } | "const" PartialTypeAlias {% posInject \p -> DTType p $2 } | "{" StreamOp StreamSize Concat "}" {% posInject \p -> DTStream p $2 $3 (map toLHS $4) } @@ -697,6 +698,7 @@ NonGenerateModuleItem :: { [ModuleItem] } | "genvar" Identifiers ";" { map Genvar $2 } | "modport" ModportItems ";" { map (uncurry Modport) $2 } | NonDeclPackageItem { map MIPackageItem $1 } + | TaskOrFunction { [MIPackageItem $1] } | NInputGateKW NInputGates ";" { map (\(a, b, c, d) -> NInputGate $1 a b c d) $2 } | NOutputGateKW NOutputGates ";" { map (\(a, b, c, d) -> NOutputGate $1 a b c d) $2 } | AttributeInstance ModuleItem { map (addMIAttr $1) $2 } @@ -843,22 +845,45 @@ PackageItems :: { [PackageItem] } | ";" PackageItems { $2 } | PITrace PackageItem PackageItems { $1 : $2 ++ $3 } PackageItem :: { [PackageItem] } + : PackageOrClassItem { $1} + | TaskOrFunction { [$1] } + +ClassItems :: { [ClassItem] } + : {- empty -} { [] } + | ";" ClassItems { $2 } + | CITrace ClassItem ClassItems { $1 : $2 ++ $3 } +ClassItem :: { [ClassItem] } + : ClassItemQualifier PackageOrClassItem { map ($1, ) $2 } + | ClassItemQualifier TaskOrFunction { [($1, $2)] } +ClassItemQualifier :: { Qualifier } + : {- empty -} { QNone } + | "static" { QStatic } + | "local" { QLocal } + | "protected" { QProtected } + +PackageOrClassItem :: { [PackageItem] } : DeclTokens(";") { map Decl $ parseDTsAsDecls $1 } | ParameterDecl(";") { map Decl $1 } | NonDeclPackageItem { $1 } NonDeclPackageItem :: { [PackageItem] } - : "typedef" Type Identifier ";" { [Decl $ ParamType Localparam $3 $2] } - | "typedef" Type Identifier DimensionsNonEmpty ";" { [Decl $ ParamType Localparam $3 (UnpackedType $2 $4)] } - | "typedef" TypedefRef Identifier ";" { [Decl $ ParamType Localparam $3 $2] } - | "function" Lifetime FuncRetAndName TFItems DeclsAndStmts endfunction StrTag {% checkTag (snd $3) $7 [Function $2 (fst $3) (snd $3) (map makeInput $4 ++ fst $5) (snd $5)] } - | "function" Lifetime "void" Identifier TFItems DeclsAndStmts endfunction StrTag {% checkTag $4 $8 [Task $2 $4 ($5 ++ fst $6) (snd $6)] } - | "task" Lifetime Identifier TFItems DeclsAndStmts endtask StrTag {% checkTag $3 $7 [Task $2 $3 ($4 ++ fst $5) (snd $5)] } - | "import" PackageImportItems ";" { map (uncurry Import) $2 } + : Typedef { [Decl $1] } + | ImportOrExport { $1 } + | ForwardTypedef ";" { $1 } + | TimeunitsDeclaration { $1 } + | Directive { [Directive $1] } + +ImportOrExport :: { [PackageItem] } + : "import" PackageImportItems ";" { map (uncurry Import) $2 } | "export" PackageImportItems ";" { map (uncurry Export) $2 } | "export" "*" "::" "*" ";" { [Export "" ""] } - | ForwardTypedef ";" { $1 } - | TimeunitsDeclaration { $1 } - | Directive { [Directive $1] } +TaskOrFunction :: { PackageItem } + : "function" Lifetime FuncRetAndName TFItems DeclsAndStmts endfunction StrTag {% checkTag (snd $3) $7 $ Function $2 (fst $3) (snd $3) (map makeInput $4 ++ fst $5) (snd $5) } + | "function" Lifetime "void" Identifier TFItems DeclsAndStmts endfunction StrTag {% checkTag $4 $8 $ Task $2 $4 ($5 ++ fst $6) (snd $6) } + | "task" Lifetime Identifier TFItems DeclsAndStmts endtask StrTag {% checkTag $3 $7 $ Task $2 $3 ($4 ++ fst $5) (snd $5) } +Typedef :: { Decl } + : "typedef" Type Identifier ";" { ParamType Localparam $3 $2 } + | "typedef" Type Identifier DimensionsNonEmpty ";" { ParamType Localparam $3 (UnpackedType $2 $4) } + | "typedef" TypedefRef Identifier ";" { ParamType Localparam $3 $2 } TypedefRef :: { Type } : Identifier "." Identifier { TypedefRef $ Dot (Ident $1) $3 } | Identifier "[" Expr "]" "." Identifier { TypedefRef $ Dot (Bit (Ident $1) $3) $6 } @@ -1391,6 +1416,8 @@ MITrace :: { ModuleItem } : PITrace { MIPackageItem $1 } PITrace :: { PackageItem } : Trace { Decl $ CommentDecl $1 } +CITrace :: { ClassItem } + : PITrace { (QNone, $1) } StmtTrace :: { Stmt } : Trace { CommentStmt $1 } Trace :: { String } diff --git a/test/basic/subroutine.sv b/test/basic/subroutine.sv index 0c70225..c3a76cd 100644 --- a/test/basic/subroutine.sv +++ b/test/basic/subroutine.sv @@ -1,8 +1,7 @@ class C #( parameter X = 1 ); - // TODO: this should be static - task dump; + static task dump; $display("C#(%0d)::dump()", X); endtask endclass