diff --git a/Language/SystemVerilog/AST.hs b/Language/SystemVerilog/AST.hs index bb05b36..7139153 100644 --- a/Language/SystemVerilog/AST.hs +++ b/Language/SystemVerilog/AST.hs @@ -11,6 +11,10 @@ module Language.SystemVerilog.AST , BinOp (..) , Sense (..) , Call (..) + , BlockItemDeclaration (..) + , Parameter (..) + , Localparam (..) + , IntegerV (..) , PortBinding , Case , Range @@ -74,35 +78,62 @@ instance Show Type where data ModuleItem = Comment String - | Parameter (Maybe Range) Identifier Expr - | Localparam (Maybe Range) Identifier Expr + | MIParameter Parameter + | MILocalparam Localparam + | MIIntegerV IntegerV | PortDecl Direction (Maybe Range) Identifier | LocalNet Type Identifier RangesOrAssignment - | Integer Identifier RangesOrAssignment | Always (Maybe Sense) Stmt | Assign LHS Expr | Instance Identifier [PortBinding] Identifier [PortBinding] + | Function (Maybe FuncRet) Identifier [(Bool, BlockItemDeclaration)] Stmt deriving Eq +-- "function inputs and outputs are inferred to be of type reg if no internal +-- data types for the ports are declared" + type PortBinding = (Identifier, Maybe Expr) +data Parameter = Parameter (Maybe Range) Identifier Expr deriving Eq +instance Show Parameter where + show (Parameter r n e) = printf "parameter %s%s = %s;" (showRange r) n (showExprConst e) + +data Localparam = Localparam (Maybe Range) Identifier Expr deriving Eq +instance Show Localparam where + show (Localparam r n e) = printf "localparam %s%s = %s;" (showRange r) n (showExprConst e) + +data IntegerV = IntegerV Identifier RangesOrAssignment deriving Eq +instance Show IntegerV where + show (IntegerV x v ) = printf "integer %s%s;" x (showRangesOrAssignment v) + instance Show ModuleItem where show thing = case thing of Comment c -> "// " ++ c - Parameter r n e -> printf "parameter %s%s = %s;" (showRange r) n (showExprConst e) - Localparam r n e -> printf "localparam %s%s = %s;" (showRange r) n (showExprConst e) + MIParameter nest -> show nest + MILocalparam nest -> show nest + MIIntegerV nest -> show nest PortDecl d r x -> printf "%s %s%s;" (show d) (showRange r) x LocalNet t x v -> printf "%s%s%s;" (show t) x (showRangesOrAssignment v) - Integer x v -> printf "integer %s%s;" x (showRangesOrAssignment v) Always Nothing b -> printf "always\n%s" $ indent $ show b Always (Just a) b -> printf "always @(%s)\n%s" (show a) $ indent $ show b Assign a b -> printf "assign %s = %s;" (show a) (show b) Instance m params i ports | null params -> printf "%s %s %s;" m i (showPorts show ports) | otherwise -> printf "%s #%s %s %s;" m (showPorts showExprConst 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) 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 ] + showFunctionItem :: (Bool, BlockItemDeclaration) -> String + showFunctionItem (b, item) = prefix ++ (show item) + where prefix = if b then "input " else "" + +type FuncRet = Either Range () + +showFuncRet :: Maybe FuncRet -> String +showFuncRet Nothing = "" +showFuncRet (Just (Left r)) = showRange $ Just r +showFuncRet (Just (Right ())) = "integer " type RangesOrAssignment = Either [Range] (Maybe Expr) @@ -290,15 +321,12 @@ instance Show LHS where show (LHSConcat a ) = printf "{%s}" (commas $ map show a) data Stmt - = Block (Maybe Identifier) [Stmt] - | StmtReg (Maybe Range) Identifier [Range] - | StmtInteger Identifier RangesOrAssignment + = Block (Maybe (Identifier, [BlockItemDeclaration])) [Stmt] | Case Expr [Case] (Maybe Stmt) | BlockingAssignment LHS Expr | NonBlockingAssignment LHS Expr | For (Identifier, Expr) Expr (Identifier, Expr) Stmt | If Expr Stmt Stmt - | StmtCall Call | Null deriving Eq @@ -306,10 +334,8 @@ commas :: [String] -> String commas = intercalate ", " instance Show Stmt where - show (Block Nothing b ) = printf "begin\n%s\nend" $ indent $ unlines' $ map show b - show (Block (Just a) b ) = printf "begin : %s\n%s\nend" a $ indent $ unlines' $ map show b - show (StmtReg r x a ) = printf "reg %s%s%s;" (showRange r) x (showRanges a) - show (StmtInteger x v ) = printf "integer %s%s;" x (showRangesOrAssignment v) + show (Block Nothing b ) = printf "begin\n%s\nend" $ indent $ unlines' $ map show b + show (Block (Just (a, i)) b ) = printf "begin : %s\n%s%s\nend" a $ indent $ unlines' $ (map show i ++ map show b) show (Case a b Nothing ) = printf "case (%s)\n%s\nendcase" (show a) (indent $ unlines' $ map showCase b) show (Case a b (Just c) ) = printf "case (%s)\n%s\n\tdefault:\n%s\nendcase" (show a) (indent $ unlines' $ map showCase b) (indent $ indent $ show c) show (BlockingAssignment a b ) = printf "%s = %s;" (show a) (show b) @@ -317,9 +343,25 @@ instance Show Stmt where show (For (a, b) c (d, e) f) = printf "for (%s = %s; %s; %s = %s)\n%s" a (show b) (show c) d (show e) $ indent $ show f show (If a b Null ) = printf "if (%s)\n%s" (show a) (indent $ show b) show (If a b c ) = printf "if (%s)\n%s\nelse\n%s" (show a) (indent $ show b) (indent $ show c) - show (StmtCall a ) = printf "%s;" (show a) show (Null ) = ";" + -- It's not obvious to me how this can be done in a top level + --show (StmtCall a ) = printf "%s;" (show a) + -- | StmtCall Call + +data BlockItemDeclaration + = BIDReg (Maybe Range) Identifier [Range] + | BIDParameter Parameter + | BIDLocalparam Localparam + | BIDIntegerV IntegerV + deriving Eq + +instance Show BlockItemDeclaration where + show (BIDReg mr x rs) = printf "reg %s%s%s;" (showRange mr) x (showRanges rs) + show (BIDParameter nest) = show nest + show (BIDLocalparam nest) = show nest + show (BIDIntegerV nest) = show nest + type Case = ([Expr], Stmt) showCase :: Case -> String diff --git a/Language/SystemVerilog/Parser/Lex.x b/Language/SystemVerilog/Parser/Lex.x index 6f25b86..cd52b94 100644 --- a/Language/SystemVerilog/Parser/Lex.x +++ b/Language/SystemVerilog/Parser/Lex.x @@ -66,6 +66,8 @@ tokens :- "end" { tok KW_end } "endcase" { tok KW_endcase } "endmodule" { tok KW_endmodule } + "endfunction" { tok KW_endfunction} + "function" { tok KW_function } "for" { tok KW_for } "if" { tok KW_if } "initial" { tok KW_initial } diff --git a/Language/SystemVerilog/Parser/Parse.y b/Language/SystemVerilog/Parser/Parse.y index be18dd2..de36740 100644 --- a/Language/SystemVerilog/Parser/Parse.y +++ b/Language/SystemVerilog/Parser/Parse.y @@ -27,7 +27,9 @@ import Language.SystemVerilog.Parser.Tokens "else" { Token KW_else _ _ } "end" { Token KW_end _ _ } "endcase" { Token KW_endcase _ _ } +"endfunction" { Token KW_endfunction _ _ } "endmodule" { Token KW_endmodule _ _ } +"function" { Token KW_function _ _ } "for" { Token KW_for _ _ } "if" { Token KW_if _ _ } "initial" { Token KW_initial _ _ } @@ -172,7 +174,7 @@ ParamDecls :: { [ModuleItem] } : ParamDecl(")") { $1 } | ParamDecl(",") ParamDecls { $1 ++ $2 } ParamDecl(delim) :: { [ModuleItem] } - : "parameter" opt(Range) DeclAsgns delim { map (uncurry $ Parameter $2) $3 } + : "parameter" opt(Range) DeclAsgns delim { map (MIParameter . (uncurry $ Parameter $2)) $3 } Identifier :: { Identifier } : simpleIdentifier { tokenString $1 } @@ -213,15 +215,45 @@ ModuleItems :: { [ModuleItem] } | ModuleItems ModuleItem { $1 ++ $2 } ModuleItem :: { [ModuleItem] } - : "parameter" opt(Range) DeclAsgns ";" { map (uncurry $ Parameter $2) $3 } - | "localparam" opt(Range) DeclAsgns ";" { map (uncurry $ Localparam $2) $3 } - | PortDecl(";") { $1 } + : PortDecl(";") { $1 } | "reg" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Reg $2) $3 } | "wire" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Wire $2) $3 } - | "integer" VariableIdentifiers ";" { map (uncurry Integer) $2 } + | ParameterDeclaration { map MIParameter $1 } + | LocalparamDeclaration { map MILocalparam $1 } + | IntegerDeclaration { map MIIntegerV $1 } | "assign" LHS "=" Expr ";" { [Assign $2 $4] } | "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] } + +FunctionItems :: { [(Bool, BlockItemDeclaration)] } + : "(" FunctionPortList ";" BlockItemDeclarations { (map ((,) True) $2) ++ (map ((,) False) $4) } + | ";" FunctionItemDeclarations { $2 } +FunctionPortList :: { [BlockItemDeclaration] } + : FunctionInputDeclaration(")") { $1 } + | FunctionInputDeclaration(",") FunctionPortList { $1 ++ $2 } +FunctionItemDeclarations :: { [(Bool, BlockItemDeclaration)] } + : FunctionItemDeclaration { $1 } + | FunctionItemDeclarations FunctionItemDeclaration { $1 ++ $2 } +FunctionItemDeclaration :: { [(Bool, BlockItemDeclaration)] } + : BlockItemDeclaration { map ((,) False) $1 } + | FunctionInputDeclaration(";") { map ((,) True ) $1 } +FunctionInputDeclaration(delim) :: { [BlockItemDeclaration] } + : "input" opt("reg") opt(Range) Identifiers delim { map (\x -> BIDReg $3 x []) $4 } + | "input" "integer" Identifiers delim { map (\x -> BIDIntegerV $ IntegerV x $ Left []) $3 } + +ParameterDeclaration :: { [Parameter] } + : "parameter" opt(Range) DeclAsgns ";" { map (uncurry $ Parameter $2) $3 } + +LocalparamDeclaration :: { [Localparam] } + : "localparam" opt(Range) DeclAsgns ";" { map (uncurry $ Localparam $2) $3 } + +IntegerDeclaration :: { [IntegerV] } + : "integer" VariableIdentifiers ";" { map (uncurry IntegerV) $2 } + +RangeOrType :: { Either Range () } + : Range { Left $1 } + | "integer" { Right () } EventControl :: { Sense } : "@" "(" Sense ")" { $3 } @@ -291,22 +323,30 @@ Stmts :: { [Stmt] } Stmt :: { Stmt } : ";" { Null } - | "begin" Stmts "end" { Block Nothing $2 } - | "begin" ":" Identifier Stmts "end" { Block (Just $3) $4 } - | "reg" opt(Range) BlockRegIdentifiers ";" { stmtsToStmt $ map (uncurry $ StmtReg $2) $3 } - | "integer" VariableIdentifiers ";" { stmtsToStmt $ map (uncurry StmtInteger) $2 } + | "begin" Stmts "end" { Block Nothing $2 } + | "begin" ":" Identifier Stmts "end" { Block (Just ($3, [])) $4 } + | "begin" ":" Identifier BlockItemDeclarations Stmts "end" { Block (Just ($3, $4)) $5 } | "if" "(" Expr ")" Stmt "else" Stmt { If $3 $5 $7 } | "if" "(" Expr ")" Stmt %prec NoElse { If $3 $5 Null } | "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 } + -- | Call ";" { StmtCall $1 } | "case" "(" Expr ")" Cases CaseDefault "endcase" { Case $3 $5 $6 } -BlockRegIdentifiers :: { [(Identifier, [Range])] } - : BlockRegIdentifier { [$1] } - | BlockRegIdentifiers "," BlockRegIdentifier { $1 ++ [$3] } -BlockRegIdentifier :: { (Identifier, [Range]) } +BlockItemDeclarations :: { [BlockItemDeclaration] } + : BlockItemDeclaration { $1 } + | BlockItemDeclarations BlockItemDeclaration { $1 ++ $2 } + +BlockItemDeclaration :: { [BlockItemDeclaration] } + : "reg" opt(Range) BlockVariableIdentifiers { map (uncurry $ BIDReg $2) $3 } + | ParameterDeclaration { map BIDParameter $1 } + | LocalparamDeclaration { map BIDLocalparam $1 } + | IntegerDeclaration { map BIDIntegerV $1 } +BlockVariableIdentifiers :: { [(Identifier, [Range])] } + : BlockVariableType { [$1] } + | BlockVariableIdentifiers "," BlockVariableType { $1 ++ [$3] } +BlockVariableType :: { (Identifier, [Range]) } : Identifier { ($1, []) } | Identifier Dimensions { ($1, $2) }