Commit 06b47b06 by Zachary Snow

preliminary support for generators

parent b0d573c5
...@@ -15,9 +15,11 @@ module Language.SystemVerilog.AST ...@@ -15,9 +15,11 @@ module Language.SystemVerilog.AST
, Parameter (..) , Parameter (..)
, Localparam (..) , Localparam (..)
, IntegerV (..) , IntegerV (..)
, GenItem (..)
, PortBinding , PortBinding
, Case , Case
, Range , Range
, GenCase
) where ) where
import Data.Bits import Data.Bits
...@@ -85,6 +87,8 @@ data ModuleItem ...@@ -85,6 +87,8 @@ data ModuleItem
| Assign LHS Expr | Assign LHS Expr
| Instance Identifier [PortBinding] Identifier [PortBinding] | Instance Identifier [PortBinding] Identifier [PortBinding]
| Function (Maybe FuncRet) Identifier [(Bool, BlockItemDeclaration)] Stmt | Function (Maybe FuncRet) Identifier [(Bool, BlockItemDeclaration)] Stmt
| Genvar Identifier
| Generate [GenItem]
deriving Eq deriving Eq
-- "function inputs and outputs are inferred to be of type reg if no internal -- "function inputs and outputs are inferred to be of type reg if no internal
...@@ -119,6 +123,8 @@ instance Show ModuleItem where ...@@ -119,6 +123,8 @@ instance Show ModuleItem where
| 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 show params) 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) 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 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 ]
...@@ -332,7 +338,7 @@ instance Show BlockItemDeclaration where ...@@ -332,7 +338,7 @@ instance Show BlockItemDeclaration where
type Case = ([Expr], Stmt) 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) showCase (a, b) = printf "%s:\n%s" (commas $ map show a) (indent $ show b)
data Call = Call Identifier [Expr] deriving Eq data Call = Call Identifier [Expr] deriving Eq
...@@ -362,3 +368,26 @@ indentedParenList [] = "()" ...@@ -362,3 +368,26 @@ indentedParenList [] = "()"
indentedParenList [x] = "(" ++ x ++ ")" indentedParenList [x] = "(" ++ x ++ ")"
indentedParenList l = indentedParenList l =
"(\n" ++ (indent $ intercalate ",\n" l) ++ "\n)" "(\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
...@@ -67,8 +67,11 @@ tokens :- ...@@ -67,8 +67,11 @@ tokens :-
"endcase" { tok KW_endcase } "endcase" { tok KW_endcase }
"endmodule" { tok KW_endmodule } "endmodule" { tok KW_endmodule }
"endfunction" { tok KW_endfunction} "endfunction" { tok KW_endfunction}
"endgenerate" { tok KW_endgenerate}
"function" { tok KW_function } "function" { tok KW_function }
"for" { tok KW_for } "for" { tok KW_for }
"generate" { tok KW_generate }
"genvar" { tok KW_genvar }
"if" { tok KW_if } "if" { tok KW_if }
"initial" { tok KW_initial } "initial" { tok KW_initial }
"inout" { tok KW_inout } "inout" { tok KW_inout }
......
...@@ -27,9 +27,12 @@ import Language.SystemVerilog.Parser.Tokens ...@@ -27,9 +27,12 @@ import Language.SystemVerilog.Parser.Tokens
"end" { Token KW_end _ _ } "end" { Token KW_end _ _ }
"endcase" { Token KW_endcase _ _ } "endcase" { Token KW_endcase _ _ }
"endfunction" { Token KW_endfunction _ _ } "endfunction" { Token KW_endfunction _ _ }
"endgenerate" { Token KW_endgenerate _ _ }
"endmodule" { Token KW_endmodule _ _ } "endmodule" { Token KW_endmodule _ _ }
"function" { Token KW_function _ _ } "function" { Token KW_function _ _ }
"for" { Token KW_for _ _ } "for" { Token KW_for _ _ }
"generate" { Token KW_generate _ _ }
"genvar" { Token KW_genvar _ _ }
"if" { Token KW_if _ _ } "if" { Token KW_if _ _ }
"initial" { Token KW_initial _ _ } "initial" { Token KW_initial _ _ }
"inout" { Token KW_inout _ _ } "inout" { Token KW_inout _ _ }
...@@ -224,6 +227,8 @@ ModuleItem :: { [ModuleItem] } ...@@ -224,6 +227,8 @@ ModuleItem :: { [ModuleItem] }
| "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] } | "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)] } FunctionItems :: { [(Bool, BlockItemDeclaration)] }
: "(" FunctionPortList ";" BlockItemDeclarations { (map ((,) True) $2) ++ (map ((,) False) $4) } : "(" FunctionPortList ";" BlockItemDeclarations { (map ((,) True) $2) ++ (map ((,) False) $4) }
...@@ -331,8 +336,7 @@ Stmt :: { Stmt } ...@@ -331,8 +336,7 @@ Stmt :: { Stmt }
| "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 } | "case" "(" Expr ")" Cases opt(CaseDefault) "endcase" { Case $3 $5 $6 }
| "case" "(" Expr ")" Cases CaseDefault "endcase" { Case $3 $5 $6 }
BlockItemDeclarations :: { [BlockItemDeclaration] } BlockItemDeclarations :: { [BlockItemDeclaration] }
: BlockItemDeclaration { $1 } : BlockItemDeclaration { $1 }
...@@ -351,15 +355,14 @@ BlockVariableType :: { (Identifier, [Range]) } ...@@ -351,15 +355,14 @@ BlockVariableType :: { (Identifier, [Range]) }
| Identifier Dimensions { ($1, $2) } | Identifier Dimensions { ($1, $2) }
Cases :: { [Case] } Cases :: { [Case] }
: { [] } : {- empty -} { [] }
| Cases Case { $1 ++ [$2] } | Cases Case { $1 ++ [$2] }
Case :: { Case } Case :: { Case }
: Exprs ":" Stmt { ($1, $3) } : Exprs ":" Stmt { ($1, $3) }
CaseDefault :: { Maybe Stmt } CaseDefault :: { Stmt }
: { Nothing } : "default" opt(":") Stmt { $3 }
| "default" ":" Stmt { Just $3 }
Number :: { String } Number :: { String }
: number { tokenString $1 } : number { tokenString $1 }
...@@ -424,6 +427,34 @@ Expr :: { Expr } ...@@ -424,6 +427,34 @@ Expr :: { Expr }
| "~^" Expr %prec RedOps { UniOp RedXnor $2 } | "~^" Expr %prec RedOps { UniOp RedXnor $2 }
| "^~" 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 parseError :: [Token] -> a
...@@ -465,5 +496,14 @@ stmtsToStmt [] = error "stmtsToStmt given empty list!" ...@@ -465,5 +496,14 @@ stmtsToStmt [] = error "stmtsToStmt given empty list!"
stmtsToStmt [s] = s stmtsToStmt [s] = s
stmtsToStmt ss = Block Nothing ss 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
} }
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