diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index fc01d75..5527362 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -646,6 +646,7 @@ PortDeclTokens(delim) :: { [DeclToken] } : DeclTokensBase(PortDeclTokens(delim), delim) { $1 } | GenericInterfaceDecl PortDeclTokens(delim) { $1 ++ $2} | GenericInterfaceDecl delim { $1 } + | AttributeInstance PortDeclTokens(delim) {% posInject \p -> DTAttr p $1 : $2 } GenericInterfaceDecl :: { [DeclToken] } : "interface" Identifier {% posInject \p -> [DTType p (\Unspecified -> InterfaceT "" Nothing), DTIdent p $2] } diff --git a/src/Language/SystemVerilog/Parser/ParseDecl.hs b/src/Language/SystemVerilog/Parser/ParseDecl.hs index 68bdfc7..39f7818 100644 --- a/src/Language/SystemVerilog/Parser/ParseDecl.hs +++ b/src/Language/SystemVerilog/Parser/ParseDecl.hs @@ -69,6 +69,7 @@ data DeclToken | DTDot Position Identifier | DTSigning Position Signing | DTLifetime Position Lifetime + | DTAttr Position Attr deriving (Show, Eq) -- entrypoints besides `parseDTsAsDeclOrStmt` use this to disallow `DTAsgn` with @@ -93,7 +94,7 @@ parseDTsAsPortDecls pieces = forbidNonEqAsgn pieces $ if isSimpleList then (simpleIdents, []) - else (portNames declarations, map (MIPackageItem . Decl) declarations) + else (portNames declarations, applyAttrs [] pieces declarations) where commaIdxs = findIndices isComma pieces identIdxs = findIndices isIdent pieces @@ -104,10 +105,15 @@ parseDTsAsPortDecls pieces = length pieces == length commaIdxs + length identIdxs simpleIdents = map extractIdent $ filter isIdent pieces - declarations = propagateDirections Input $ parseDTsAsDecls pieces + declarations = propagateDirections Input $ parseDTsAsDecls pieces' extractIdent = \(DTIdent _ x) -> x + pieces' = filter (not . isDTAttr) pieces + isDTAttr :: DeclToken -> Bool + isDTAttr DTAttr{} = True + isDTAttr _ = False + propagateDirections :: Direction -> [Decl] -> [Decl] propagateDirections dir (decl @ (Variable _ InterfaceT{} _ _ _) : decls) = decl : propagateDirections dir decls @@ -128,6 +134,23 @@ parseDTsAsPortDecls pieces = portName decl = error $ "unexpected non-variable port declaration: " ++ (show decl) + applyAttrs :: [Attr] -> [DeclToken] -> [Decl] -> [ModuleItem] + applyAttrs _ [] [] = [] + applyAttrs _ tokens (CommentDecl c : decls) = + MIPackageItem (Decl $ CommentDecl c) : applyAttrs [] tokens decls + applyAttrs attrs (DTAttr _ attr : tokens) decls = + applyAttrs (attr : attrs) tokens decls + applyAttrs attrs [] [decl] = + [wrapDecl attrs decl] + applyAttrs attrs (DTComma{} : tokens) (decl : decls) = + wrapDecl attrs decl : applyAttrs attrs tokens decls + applyAttrs attrs (_ : tokens) decls = + applyAttrs attrs tokens decls + applyAttrs _ [] _ = error "applyAttrs internal invariant failed" + + wrapDecl :: [Attr] -> Decl -> ModuleItem + wrapDecl attrs decl = foldr MIAttr (MIPackageItem $ Decl decl) attrs + -- [PUBLIC]: parser for single (semicolon-terminated) declarations (including -- parameters) and module instantiations @@ -494,3 +517,4 @@ tokPos (DTStream p _ _ _) = p tokPos (DTDot p _) = p tokPos (DTSigning p _) = p tokPos (DTLifetime p _) = p +tokPos (DTAttr p _) = p diff --git a/test/basic/attr.sv b/test/basic/attr.sv index c6a9daa..94b8008 100644 --- a/test/basic/attr.sv +++ b/test/basic/attr.sv @@ -1,7 +1,23 @@ +module Example( + input a, b, + (* who=1 *) output c, + (* what=2 *) output d, e, + input f, + (* when=3 *) (* where=4 *) output g, h, i +); +endmodule + (* a=1 *) module top; - (* foo="bar" *) logic x; + (* foo="bar" *) reg x; initial begin x = 1; $display(x); end + + reg a, b; + wire c; + wire d, e; + reg f; + wire g, h, i; + Example m(a,b,c,d,e,f,g,h,i); endmodule diff --git a/test/basic/attr.v b/test/basic/attr.v index cef2d47..eadb3c6 100644 --- a/test/basic/attr.v +++ b/test/basic/attr.v @@ -1,7 +1 @@ -(* a=1 *) module top; - (* foo="bar" *) reg x; - initial begin - x = 1; - $display(x); - end -endmodule +`include "attr.sv"