Commit 57630b77 by Zachary Snow

preliminary support for functions

parent 6c88994e
...@@ -11,6 +11,10 @@ module Language.SystemVerilog.AST ...@@ -11,6 +11,10 @@ module Language.SystemVerilog.AST
, BinOp (..) , BinOp (..)
, Sense (..) , Sense (..)
, Call (..) , Call (..)
, BlockItemDeclaration (..)
, Parameter (..)
, Localparam (..)
, IntegerV (..)
, PortBinding , PortBinding
, Case , Case
, Range , Range
...@@ -74,35 +78,62 @@ instance Show Type where ...@@ -74,35 +78,62 @@ instance Show Type where
data ModuleItem data ModuleItem
= Comment String = Comment String
| Parameter (Maybe Range) Identifier Expr | MIParameter Parameter
| Localparam (Maybe Range) Identifier Expr | MILocalparam Localparam
| MIIntegerV IntegerV
| PortDecl Direction (Maybe Range) Identifier | PortDecl Direction (Maybe Range) Identifier
| LocalNet Type Identifier RangesOrAssignment | LocalNet Type Identifier RangesOrAssignment
| Integer Identifier RangesOrAssignment
| Always (Maybe Sense) Stmt | Always (Maybe Sense) Stmt
| Assign LHS Expr | Assign LHS Expr
| Instance Identifier [PortBinding] Identifier [PortBinding] | Instance Identifier [PortBinding] Identifier [PortBinding]
| Function (Maybe FuncRet) Identifier [(Bool, BlockItemDeclaration)] Stmt
deriving Eq 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) 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 instance Show ModuleItem where
show thing = case thing of show thing = case thing of
Comment c -> "// " ++ c Comment c -> "// " ++ c
Parameter r n e -> printf "parameter %s%s = %s;" (showRange r) n (showExprConst e) MIParameter nest -> show nest
Localparam r n e -> printf "localparam %s%s = %s;" (showRange r) n (showExprConst e) MILocalparam nest -> show nest
MIIntegerV nest -> show nest
PortDecl d r x -> printf "%s %s%s;" (show d) (showRange r) x 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) 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 Nothing b -> printf "always\n%s" $ indent $ show b
Always (Just a) b -> printf "always @(%s)\n%s" (show a) $ 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) Assign a b -> printf "assign %s = %s;" (show a) (show b)
Instance m params i ports Instance m params i ports
| null params -> printf "%s %s %s;" m i (showPorts show 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) | 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 where
showPorts :: (Expr -> String) -> [(Identifier, Maybe Expr)] -> String 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 ] 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) type RangesOrAssignment = Either [Range] (Maybe Expr)
...@@ -290,15 +321,12 @@ instance Show LHS where ...@@ -290,15 +321,12 @@ instance Show LHS where
show (LHSConcat a ) = printf "{%s}" (commas $ map show a) show (LHSConcat a ) = printf "{%s}" (commas $ map show a)
data Stmt data Stmt
= Block (Maybe Identifier) [Stmt] = Block (Maybe (Identifier, [BlockItemDeclaration])) [Stmt]
| StmtReg (Maybe Range) Identifier [Range]
| StmtInteger Identifier RangesOrAssignment
| Case Expr [Case] (Maybe Stmt) | Case Expr [Case] (Maybe Stmt)
| BlockingAssignment LHS Expr | BlockingAssignment LHS Expr
| NonBlockingAssignment LHS Expr | NonBlockingAssignment LHS Expr
| For (Identifier, Expr) Expr (Identifier, Expr) Stmt | For (Identifier, Expr) Expr (Identifier, Expr) Stmt
| If Expr Stmt Stmt | If Expr Stmt Stmt
| StmtCall Call
| Null | Null
deriving Eq deriving Eq
...@@ -306,10 +334,8 @@ commas :: [String] -> String ...@@ -306,10 +334,8 @@ commas :: [String] -> String
commas = intercalate ", " commas = intercalate ", "
instance Show Stmt where instance Show Stmt where
show (Block Nothing b ) = printf "begin\n%s\nend" $ indent $ unlines' $ map show b 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 (Block (Just (a, i)) b ) = printf "begin : %s\n%s%s\nend" a $ indent $ unlines' $ (map show i ++ 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 (Case a b Nothing ) = printf "case (%s)\n%s\nendcase" (show a) (indent $ unlines' $ map showCase 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 (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) show (BlockingAssignment a b ) = printf "%s = %s;" (show a) (show b)
...@@ -317,9 +343,25 @@ instance Show Stmt where ...@@ -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 (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 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 (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 ) = ";" 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) type Case = ([Expr], Stmt)
showCase :: Case -> String showCase :: Case -> String
......
...@@ -66,6 +66,8 @@ tokens :- ...@@ -66,6 +66,8 @@ tokens :-
"end" { tok KW_end } "end" { tok KW_end }
"endcase" { tok KW_endcase } "endcase" { tok KW_endcase }
"endmodule" { tok KW_endmodule } "endmodule" { tok KW_endmodule }
"endfunction" { tok KW_endfunction}
"function" { tok KW_function }
"for" { tok KW_for } "for" { tok KW_for }
"if" { tok KW_if } "if" { tok KW_if }
"initial" { tok KW_initial } "initial" { tok KW_initial }
......
...@@ -27,7 +27,9 @@ import Language.SystemVerilog.Parser.Tokens ...@@ -27,7 +27,9 @@ import Language.SystemVerilog.Parser.Tokens
"else" { Token KW_else _ _ } "else" { Token KW_else _ _ }
"end" { Token KW_end _ _ } "end" { Token KW_end _ _ }
"endcase" { Token KW_endcase _ _ } "endcase" { Token KW_endcase _ _ }
"endfunction" { Token KW_endfunction _ _ }
"endmodule" { Token KW_endmodule _ _ } "endmodule" { Token KW_endmodule _ _ }
"function" { Token KW_function _ _ }
"for" { Token KW_for _ _ } "for" { Token KW_for _ _ }
"if" { Token KW_if _ _ } "if" { Token KW_if _ _ }
"initial" { Token KW_initial _ _ } "initial" { Token KW_initial _ _ }
...@@ -172,7 +174,7 @@ ParamDecls :: { [ModuleItem] } ...@@ -172,7 +174,7 @@ ParamDecls :: { [ModuleItem] }
: ParamDecl(")") { $1 } : ParamDecl(")") { $1 }
| ParamDecl(",") ParamDecls { $1 ++ $2 } | ParamDecl(",") ParamDecls { $1 ++ $2 }
ParamDecl(delim) :: { [ModuleItem] } 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 } Identifier :: { Identifier }
: simpleIdentifier { tokenString $1 } : simpleIdentifier { tokenString $1 }
...@@ -213,15 +215,45 @@ ModuleItems :: { [ModuleItem] } ...@@ -213,15 +215,45 @@ ModuleItems :: { [ModuleItem] }
| ModuleItems ModuleItem { $1 ++ $2 } | ModuleItems ModuleItem { $1 ++ $2 }
ModuleItem :: { [ModuleItem] } ModuleItem :: { [ModuleItem] }
: "parameter" opt(Range) DeclAsgns ";" { map (uncurry $ Parameter $2) $3 } : PortDecl(";") { $1 }
| "localparam" opt(Range) DeclAsgns ";" { map (uncurry $ Localparam $2) $3 }
| PortDecl(";") { $1 }
| "reg" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Reg $2) $3 } | "reg" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Reg $2) $3 }
| "wire" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Wire $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] } | "assign" LHS "=" Expr ";" { [Assign $2 $4] }
| "always" opt(EventControl) Stmt { [Always $2 $3] } | "always" opt(EventControl) Stmt { [Always $2 $3] }
| Identifier ParameterBindings Identifier Bindings ";" { [Instance $1 $2 $3 $4] } | 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 } EventControl :: { Sense }
: "@" "(" Sense ")" { $3 } : "@" "(" Sense ")" { $3 }
...@@ -291,22 +323,30 @@ Stmts :: { [Stmt] } ...@@ -291,22 +323,30 @@ Stmts :: { [Stmt] }
Stmt :: { Stmt } Stmt :: { Stmt }
: ";" { Null } : ";" { Null }
| "begin" Stmts "end" { Block Nothing $2 } | "begin" Stmts "end" { Block Nothing $2 }
| "begin" ":" Identifier Stmts "end" { Block (Just $3) $4 } | "begin" ":" Identifier Stmts "end" { Block (Just ($3, [])) $4 }
| "reg" opt(Range) BlockRegIdentifiers ";" { stmtsToStmt $ map (uncurry $ StmtReg $2) $3 } | "begin" ":" Identifier BlockItemDeclarations Stmts "end" { Block (Just ($3, $4)) $5 }
| "integer" VariableIdentifiers ";" { stmtsToStmt $ map (uncurry StmtInteger) $2 }
| "if" "(" Expr ")" Stmt "else" Stmt { If $3 $5 $7 } | "if" "(" Expr ")" Stmt "else" Stmt { If $3 $5 $7 }
| "if" "(" Expr ")" Stmt %prec NoElse { If $3 $5 Null } | "if" "(" Expr ")" Stmt %prec NoElse { If $3 $5 Null }
| "for" "(" Identifier "=" Expr ";" Expr ";" Identifier "=" Expr ")" Stmt { For ($3, $5) $7 ($9, $11) $13 } | "for" "(" Identifier "=" Expr ";" Expr ";" Identifier "=" Expr ")" Stmt { For ($3, $5) $7 ($9, $11) $13 }
| LHS "=" Expr ";" { BlockingAssignment $1 $3 } | LHS "=" Expr ";" { BlockingAssignment $1 $3 }
| LHS "<=" Expr ";" { NonBlockingAssignment $1 $3 } | LHS "<=" Expr ";" { NonBlockingAssignment $1 $3 }
| Call ";" { StmtCall $1 } -- | Call ";" { StmtCall $1 }
| "case" "(" Expr ")" Cases CaseDefault "endcase" { Case $3 $5 $6 } | "case" "(" Expr ")" Cases CaseDefault "endcase" { Case $3 $5 $6 }
BlockRegIdentifiers :: { [(Identifier, [Range])] } BlockItemDeclarations :: { [BlockItemDeclaration] }
: BlockRegIdentifier { [$1] } : BlockItemDeclaration { $1 }
| BlockRegIdentifiers "," BlockRegIdentifier { $1 ++ [$3] } | BlockItemDeclarations BlockItemDeclaration { $1 ++ $2 }
BlockRegIdentifier :: { (Identifier, [Range]) }
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 { ($1, []) }
| Identifier Dimensions { ($1, $2) } | Identifier Dimensions { ($1, $2) }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment