diff --git a/Language/SystemVerilog/AST.hs b/Language/SystemVerilog/AST.hs index 7a493b7..ae30a4d 100644 --- a/Language/SystemVerilog/AST.hs +++ b/Language/SystemVerilog/AST.hs @@ -15,9 +15,11 @@ module Language.SystemVerilog.AST , Parameter (..) , Localparam (..) , IntegerV (..) + , GenItem (..) , PortBinding , Case , Range + , GenCase ) where import Data.Bits @@ -85,6 +87,8 @@ data ModuleItem | Assign LHS Expr | Instance Identifier [PortBinding] Identifier [PortBinding] | Function (Maybe FuncRet) Identifier [(Bool, BlockItemDeclaration)] Stmt + | Genvar Identifier + | Generate [GenItem] deriving Eq -- "function inputs and outputs are inferred to be of type reg if no internal @@ -119,6 +123,8 @@ instance Show ModuleItem where | null params -> printf "%s %s %s;" m i (showPorts show ports) | otherwise -> printf "%s #%s %s %s;" m (showPorts show params) i (showPorts show ports) Function t x i b -> printf "function %s%s;\n%s\n%s\nendfunction" (showFuncRet t) x (indent $ unlines' $ map showFunctionItem i) (indent $ show b) + Genvar x -> printf "genvar %s;" x + Generate b -> printf "generate\n%s\nendgenerate" (indent $ unlines' $ map show b) where showPorts :: (Expr -> String) -> [(Identifier, Maybe Expr)] -> String showPorts s ports = indentedParenList [ if i == "" then show (fromJust arg) else printf ".%s(%s)" i (if isJust arg then s $ fromJust arg else "") | (i, arg) <- ports ] @@ -332,7 +338,7 @@ instance Show BlockItemDeclaration where type Case = ([Expr], Stmt) -showCase :: Case -> String +showCase :: (Show x, Show y) => ([x], y) -> String showCase (a, b) = printf "%s:\n%s" (commas $ map show a) (indent $ show b) data Call = Call Identifier [Expr] deriving Eq @@ -362,3 +368,26 @@ indentedParenList [] = "()" indentedParenList [x] = "(" ++ x ++ ")" indentedParenList l = "(\n" ++ (indent $ intercalate ",\n" l) ++ "\n)" + +type GenCase = ([Expr], GenItem) + +data GenItem + = GenBlock (Maybe Identifier) [GenItem] + | GenCase Expr [GenCase] (Maybe GenItem) + | GenFor (Identifier, Expr) Expr (Identifier, Expr) Identifier [GenItem] + | GenIf Expr GenItem GenItem + | GenNull + | GenModuleItem ModuleItem + deriving Eq + +instance Show GenItem where + showList i _ = unlines' $ map show i + show (GenBlock Nothing i) = printf "begin\n%s\nend" (indent $ unlines' $ map show i) + show (GenBlock (Just x) i) = printf "begin : %s\n%s\nend" x (indent $ unlines' $ map show i) + show (GenCase e c Nothing ) = printf "case (%s)\n%s\nendcase" (show e) (indent $ unlines' $ map showCase c) + show (GenCase e c (Just d)) = printf "case (%s)\n%s\n\tdefault:\n%s\nendcase" (show e) (indent $ unlines' $ map showCase c) (indent $ indent $ show d) + show (GenIf e a GenNull) = printf "if (%s)\n%s" (show e) (indent $ show a) + show (GenIf e a b ) = printf "if (%s)\n%s\nelse\n%s" (show e) (indent $ show a) (indent $ show b) + show (GenFor (x1, e1) c (x2, e2) x is) = printf "for (%s = %s; %s; %s = %s) %s" x1 (show e1) (show c) x2 (show e2) (show $ GenBlock (Just x) is) + show GenNull = ";" + show (GenModuleItem item) = show item diff --git a/Language/SystemVerilog/Parser/Lex.x b/Language/SystemVerilog/Parser/Lex.x index cd52b94..860eb59 100644 --- a/Language/SystemVerilog/Parser/Lex.x +++ b/Language/SystemVerilog/Parser/Lex.x @@ -67,8 +67,11 @@ tokens :- "endcase" { tok KW_endcase } "endmodule" { tok KW_endmodule } "endfunction" { tok KW_endfunction} + "endgenerate" { tok KW_endgenerate} "function" { tok KW_function } "for" { tok KW_for } + "generate" { tok KW_generate } + "genvar" { tok KW_genvar } "if" { tok KW_if } "initial" { tok KW_initial } "inout" { tok KW_inout } diff --git a/Language/SystemVerilog/Parser/Parse.y b/Language/SystemVerilog/Parser/Parse.y index 133881f..c9aa43b 100644 --- a/Language/SystemVerilog/Parser/Parse.y +++ b/Language/SystemVerilog/Parser/Parse.y @@ -27,9 +27,12 @@ import Language.SystemVerilog.Parser.Tokens "end" { Token KW_end _ _ } "endcase" { Token KW_endcase _ _ } "endfunction" { Token KW_endfunction _ _ } +"endgenerate" { Token KW_endgenerate _ _ } "endmodule" { Token KW_endmodule _ _ } "function" { Token KW_function _ _ } "for" { Token KW_for _ _ } +"generate" { Token KW_generate _ _ } +"genvar" { Token KW_genvar _ _ } "if" { Token KW_if _ _ } "initial" { Token KW_initial _ _ } "inout" { Token KW_inout _ _ } @@ -224,6 +227,8 @@ ModuleItem :: { [ModuleItem] } | "always" opt(EventControl) Stmt { [Always $2 $3] } | Identifier ParameterBindings Identifier Bindings ";" { [Instance $1 $2 $3 $4] } | "function" opt(RangeOrType) Identifier FunctionItems Stmt "endfunction" { [Function $2 $3 $4 $5] } + | "genvar" Identifiers ";" { map Genvar $2 } + | "generate" GenItems "endgenerate" { [Generate $2] } FunctionItems :: { [(Bool, BlockItemDeclaration)] } : "(" FunctionPortList ";" BlockItemDeclarations { (map ((,) True) $2) ++ (map ((,) False) $4) } @@ -331,8 +336,7 @@ Stmt :: { Stmt } | "for" "(" Identifier "=" Expr ";" Expr ";" Identifier "=" Expr ")" Stmt { For ($3, $5) $7 ($9, $11) $13 } | LHS "=" Expr ";" { BlockingAssignment $1 $3 } | LHS "<=" Expr ";" { NonBlockingAssignment $1 $3 } - -- | Call ";" { StmtCall $1 } - | "case" "(" Expr ")" Cases CaseDefault "endcase" { Case $3 $5 $6 } + | "case" "(" Expr ")" Cases opt(CaseDefault) "endcase" { Case $3 $5 $6 } BlockItemDeclarations :: { [BlockItemDeclaration] } : BlockItemDeclaration { $1 } @@ -351,15 +355,14 @@ BlockVariableType :: { (Identifier, [Range]) } | Identifier Dimensions { ($1, $2) } Cases :: { [Case] } -: { [] } -| Cases Case { $1 ++ [$2] } + : {- empty -} { [] } + | Cases Case { $1 ++ [$2] } Case :: { Case } -: Exprs ":" Stmt { ($1, $3) } + : Exprs ":" Stmt { ($1, $3) } -CaseDefault :: { Maybe Stmt } -: { Nothing } -| "default" ":" Stmt { Just $3 } +CaseDefault :: { Stmt } + : "default" opt(":") Stmt { $3 } Number :: { String } : number { tokenString $1 } @@ -424,6 +427,34 @@ Expr :: { Expr } | "~^" Expr %prec RedOps { UniOp RedXnor $2 } | "^~" Expr %prec RedOps { UniOp RedXnor $2 } +GenItemOrNull :: { GenItem } + : GenItem { $1 } + | ";" { GenNull } + +GenItems :: { [GenItem] } + : {- empty -} { [] } + | GenItems GenItem { $1 ++ [$2] } + +GenItem :: { GenItem } + : "if" "(" Expr ")" GenItemOrNull "else" GenItemOrNull { GenIf $3 $5 $7 } + | "if" "(" Expr ")" GenItemOrNull %prec NoElse { GenIf $3 $5 GenNull } + | "begin" GenItems "end" { GenBlock Nothing $2 } + | "begin" ":" Identifier GenItems "end" { GenBlock (Just $3) $4 } + | "case" "(" Expr ")" GenCases opt(GenCaseDefault) "endcase" { GenCase $3 $5 $6 } + | "for" "(" Identifier "=" Expr ";" Expr ";" Identifier "=" Expr ")" "begin" ":" Identifier GenItems "end" { GenFor ($3, $5) $7 ($9, $11) $15 $16 } + -- TODO: We should restrict it to the module items that are actually allowed. + | ModuleItem { genItemsToGenItem $ map GenModuleItem $1 } + +GenCases :: { [GenCase] } + : {- empty -} { [] } + | GenCases GenCase { $1 ++ [$2] } + +GenCase :: { GenCase } + : Exprs ":" GenItemOrNull { ($1, $3) } + +GenCaseDefault :: { GenItem } + : "default" opt(":") GenItemOrNull { $3 } + { parseError :: [Token] -> a @@ -465,5 +496,14 @@ stmtsToStmt [] = error "stmtsToStmt given empty list!" stmtsToStmt [s] = s stmtsToStmt ss = Block Nothing ss +moduleItemsToSingleGenItem :: [ModuleItem] -> GenItem +moduleItemsToSingleGenItem [x] = GenModuleItem x +moduleItemsToSingleGenItem other = error $ "multiple module items in a generate block where only one was allowed" ++ show other + +genItemsToGenItem :: [GenItem] -> GenItem +genItemsToGenItem [] = error "genItemsToGenItem given empty list!" +genItemsToGenItem [x] = x +genItemsToGenItem xs = GenBlock Nothing xs + }