From 66989b044689a9095012bbf1425e61d10b7e01da Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 9 Sep 2019 07:38:14 +0200 Subject: [PATCH] language support for parameter type bindings --- src/Convert/Struct.hs | 1 + src/Convert/Traverse.hs | 8 +++- src/Language/SystemVerilog/AST/Expr.hs | 9 ++++- src/Language/SystemVerilog/AST/ModuleItem.hs | 21 ++++++++-- src/Language/SystemVerilog/AST/Type.hs | 3 +- src/Language/SystemVerilog/Parser/Parse.y | 39 +++++++++++++------ .../SystemVerilog/Parser/ParseDecl.hs | 2 +- 7 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/Convert/Struct.hs b/src/Convert/Struct.hs index 57789fb..a3f30a2 100644 --- a/src/Convert/Struct.hs +++ b/src/Convert/Struct.hs @@ -445,6 +445,7 @@ convertAsgn structs types (lhs, expr) = where items' = map mapItem items mapItem (mx, e) = (mx, snd $ convertSubExpr e) + convertSubExpr Nil = (Implicit Unspecified [], Nil) -- lookup the range of a field in its unstructured type lookupUnstructRange :: TypeFunc -> Identifier -> Range diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index cce9fd0..f3142c0 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -464,6 +464,7 @@ traverseNestedExprsM mapper = exprMapper let names = map fst l exprs <- mapM exprMapper $ map snd l return $ Pattern $ zip names exprs + em (Nil) = return Nil exprMapperHelpers :: Monad m => MapperM m Expr -> (MapperM m Range, MapperM m (Maybe Expr), MapperM m Decl, MapperM m LHS, MapperM m Type) @@ -524,6 +525,11 @@ traverseExprsM' strat exprMapper = moduleItemMapper portBindingMapper (p, me) = maybeExprMapper me >>= \me' -> return (p, me') + paramBindingMapper (p, Left t) = + typeMapper t >>= \t' -> return (p, Left t') + paramBindingMapper (p, Right e) = + exprMapper e >>= \e' -> return (p, Right e') + moduleItemMapper (MIAttr attr mi) = -- note: we exclude expressions in attributes from conversion return $ MIAttr attr mi @@ -567,7 +573,7 @@ traverseExprsM' strat exprMapper = moduleItemMapper else return stmts return $ MIPackageItem $ Task lifetime f decls' stmts' moduleItemMapper (Instance m p x r l) = do - p' <- mapM portBindingMapper p + p' <- mapM paramBindingMapper p l' <- mapM portBindingMapper l r' <- mapM rangeMapper r return $ Instance m p' x r' l' diff --git a/src/Language/SystemVerilog/AST/Expr.hs b/src/Language/SystemVerilog/AST/Expr.hs index 5dbfa5e..8988d5a 100644 --- a/src/Language/SystemVerilog/AST/Expr.hs +++ b/src/Language/SystemVerilog/AST/Expr.hs @@ -8,6 +8,7 @@ module Language.SystemVerilog.AST.Expr ( Expr (..) , Range + , TypeOrExpr , Args (..) , PartSelectMode (..) , showAssignment @@ -30,6 +31,8 @@ import {-# SOURCE #-} Language.SystemVerilog.AST.Type type Range = (Expr, Expr) +type TypeOrExpr = Either Type Expr + data Expr = String String | Number String @@ -44,13 +47,15 @@ data Expr | UniOp UniOp Expr | BinOp BinOp Expr Expr | Mux Expr Expr Expr - | Cast (Either Type Expr) Expr - | Bits (Either Type Expr) + | Cast TypeOrExpr Expr + | Bits TypeOrExpr | Dot Expr Identifier | Pattern [(Maybe Identifier, Expr)] + | Nil deriving (Eq, Ord) instance Show Expr where + show (Nil ) = "" show (Number str ) = str show (Ident str ) = str show (PSIdent x y ) = printf "%s::%s" x y diff --git a/src/Language/SystemVerilog/AST/ModuleItem.hs b/src/Language/SystemVerilog/AST/ModuleItem.hs index 6891d49..f574ecf 100644 --- a/src/Language/SystemVerilog/AST/ModuleItem.hs +++ b/src/Language/SystemVerilog/AST/ModuleItem.hs @@ -8,6 +8,7 @@ module Language.SystemVerilog.AST.ModuleItem ( ModuleItem (..) , PortBinding + , ParamBinding , ModportDecl , AlwaysKW (..) , NInputGateKW (..) @@ -16,6 +17,7 @@ module Language.SystemVerilog.AST.ModuleItem import Data.List (intercalate) import Data.Maybe (maybe, fromJust, isJust) +import Data.Either (either) import Text.Printf (printf) import Language.SystemVerilog.AST.ShowHelp @@ -23,7 +25,7 @@ import Language.SystemVerilog.AST.ShowHelp import Language.SystemVerilog.AST.Attr (Attr) import Language.SystemVerilog.AST.Decl (Direction) import Language.SystemVerilog.AST.Description (PackageItem) -import Language.SystemVerilog.AST.Expr (Expr(Ident), Range, showRanges) +import Language.SystemVerilog.AST.Expr (Expr(Ident, Nil), Range, TypeOrExpr, showRanges) import Language.SystemVerilog.AST.GenItem (GenItem) import Language.SystemVerilog.AST.LHS (LHS) import Language.SystemVerilog.AST.Stmt (Stmt, AssertionItem) @@ -34,7 +36,7 @@ data ModuleItem | AlwaysC AlwaysKW Stmt | Assign (Maybe Expr) LHS Expr | Defparam LHS Expr - | Instance Identifier [PortBinding] Identifier (Maybe Range) [PortBinding] + | Instance Identifier [ParamBinding] Identifier (Maybe Range) [PortBinding] | Genvar Identifier | Generate [GenItem] | Modport Identifier [ModportDecl] @@ -65,8 +67,8 @@ instance Show ModuleItem where else printf "%s : %s" (fromJust mx) (show a) show (Instance m params i r ports) = if null params - then printf "%s %s%s%s;" m i rStr (showPorts ports) - else printf "%s #%s %s%s%s;" m (showPorts params) i rStr (showPorts ports) + then printf "%s %s%s%s;" m i rStr (showPorts ports) + else printf "%s #%s %s%s%s;" m (showParams params) i rStr (showPorts ports) where rStr = maybe "" (\a -> showRanges [a] ++ " ") r showPorts :: [PortBinding] -> String @@ -79,6 +81,15 @@ showPort (i, arg) = then show (fromJust arg) else printf ".%s(%s)" i (if isJust arg then show $ fromJust arg else "") +showParams :: [ParamBinding] -> String +showParams params = indentedParenList $ map showParam params + +showParam :: ParamBinding -> String +showParam ("*", Right Nil) = ".*" +showParam (i, arg) = + printf fmt i (either show show arg) + where fmt = if i == "" then "%s%s" else ".%s(%s)" + showModportDecl :: ModportDecl -> String showModportDecl (dir, ident, me) = if me == Just (Ident ident) @@ -87,6 +98,8 @@ showModportDecl (dir, ident, me) = type PortBinding = (Identifier, Maybe Expr) +type ParamBinding = (Identifier, TypeOrExpr) + type ModportDecl = (Direction, Identifier, Maybe Expr) data AlwaysKW diff --git a/src/Language/SystemVerilog/AST/Type.hs b/src/Language/SystemVerilog/AST/Type.hs index 41b6cb1..a02a975 100644 --- a/src/Language/SystemVerilog/AST/Type.hs +++ b/src/Language/SystemVerilog/AST/Type.hs @@ -95,7 +95,8 @@ nullRange :: Type -> ([Range] -> Type) nullRange t [] = t nullRange t [(Number "0", Number "0")] = t nullRange t other = - error $ "non vector type " ++ show t ++ " cannot have a range" + error $ "non vector type " ++ show t ++ + " cannot have a range: " ++ show other data Signing = Unspecified diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index 3f02eb0..2d5f157 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -554,9 +554,9 @@ DeclTokens(delim) :: { [DeclToken] } | AsgnOp Expr "," DeclTokens(delim) { [DTAsgn $1 $2, DTComma] ++ $4 } | AsgnOp Expr delim { [DTAsgn $1 $2] } DeclToken :: { DeclToken } - : DeclOrStmtToken { $1 } - | ParameterBindings { DTParams $1 } - | ModuleInstantiation { DTInstance $1 } + : DeclOrStmtToken { $1 } + | ParameterBindings { DTParams $1 } + | PortBindings { DTInstance $1 } DeclOrStmtTokens(delim) :: { [DeclToken] } : DeclOrStmtToken delim { [$1] } @@ -766,9 +766,6 @@ Lifetime :: { Lifetime } : "static" { Static } | "automatic" { Automatic } -ModuleInstantiation :: { [PortBinding] } - : "(" Bindings ")" { $2 } - TFItems :: { [Decl] } : "(" DeclTokens(")") ";" { parseDTsAsDecls $2 } | "(" ")" ";" { [] } @@ -819,6 +816,28 @@ LHSs :: { [LHS] } : LHS { [$1] } | LHSs "," LHS { $1 ++ [$3] } +PortBindings :: { [PortBinding] } + : "(" ")" { [] } + | "(" PortBindingsInside ")" { $2 } +PortBindingsInside :: { [PortBinding] } + : PortBinding { [$1] } + | PortBinding "," PortBindingsInside { $1 : $3} +PortBinding :: { PortBinding } + : "." Identifier "(" opt(Expr) ")" { ($2, $4) } + | "." Identifier { ($2, Just $ Ident $2) } + | Expr { ("", Just $1) } + | ".*" { ("*", Nothing) } + +ParameterBindings :: { [ParamBinding] } + : "#" "(" ParamBindingsInside ")" { $3 } +ParamBindingsInside :: { [ParamBinding] } + : ParamBinding { [$1] } + | ParamBinding "," ParamBindingsInside { $1 : $3} +ParamBinding :: { ParamBinding } + : "." Identifier "(" TypeOrExpr ")" { ($2, $4) } + | "." Identifier "(" ")" { ($2, Right Nil) } + | TypeOrExpr { ("", $1) } + Bindings :: { [(Identifier, Maybe Expr)] } : {- empty -} { [] } | BindingsNonEmpty { $1 } @@ -831,9 +850,6 @@ Binding :: { (Identifier, Maybe Expr) } | Expr { ("", Just $1) } | ".*" { ("*", Nothing) } -ParameterBindings :: { [(Identifier, Maybe Expr)] } - : "#" "(" BindingsNonEmpty ")" { $3 } - Stmts :: { [Stmt] } : {- empty -} { [] } | Stmts Stmt { $1 ++ [$2] } @@ -987,16 +1003,17 @@ Exprs :: { [Expr] } : Expr { [$1] } | Exprs "," Expr { $1 ++ [$3] } -BitsArg :: { Either Type Expr } +TypeOrExpr :: { TypeOrExpr } : TypeNonIdent { Left $1 } | Expr { Right $1 } + Expr :: { Expr } : "(" Expr ")" { $2 } | String { String $1 } | Number { Number $1 } | Identifier "(" CallArgs ")" { Call (Nothing) $1 $3 } | Identifier "::" Identifier "(" CallArgs ")" { Call (Just $1) $3 $5 } - | "$bits" "(" BitsArg ")" { Bits $3 } + | "$bits" "(" TypeOrExpr ")" { Bits $3 } | Identifier { Ident $1 } | Identifier "::" Identifier { PSIdent $1 $3 } | Expr PartSelect { Range $1 (fst $2) (snd $2) } diff --git a/src/Language/SystemVerilog/Parser/ParseDecl.hs b/src/Language/SystemVerilog/Parser/ParseDecl.hs index 572e087..5e77af7 100644 --- a/src/Language/SystemVerilog/Parser/ParseDecl.hs +++ b/src/Language/SystemVerilog/Parser/ParseDecl.hs @@ -53,7 +53,7 @@ data DeclToken | DTPSIdent Identifier Identifier | DTDir Direction | DTType (Signing -> [Range] -> Type) - | DTParams [PortBinding] + | DTParams [ParamBinding] | DTInstance [PortBinding] | DTBit Expr | DTConcat [LHS]