2019-02-08 05:49:12 +01:00
|
|
|
{
|
2019-02-18 09:59:17 +01:00
|
|
|
module Language.SystemVerilog.Parser.Parse (descriptions) where
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
import Data.List
|
2019-02-10 00:35:15 +01:00
|
|
|
import Data.Maybe
|
2019-02-24 09:06:40 +01:00
|
|
|
|
2019-02-08 06:19:39 +01:00
|
|
|
import Language.SystemVerilog.AST
|
|
|
|
|
import Language.SystemVerilog.Parser.Tokens
|
2019-02-08 05:49:12 +01:00
|
|
|
}
|
|
|
|
|
|
2019-02-18 09:59:17 +01:00
|
|
|
%name descriptions
|
2019-02-08 05:49:12 +01:00
|
|
|
%tokentype { Token }
|
|
|
|
|
%error { parseError }
|
|
|
|
|
|
2019-02-10 23:46:18 +01:00
|
|
|
%expect 0
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
%token
|
|
|
|
|
|
2019-02-18 06:26:43 +01:00
|
|
|
"always" { Token KW_always _ _ }
|
|
|
|
|
"always_comb" { Token KW_always_comb _ _ }
|
|
|
|
|
"always_ff" { Token KW_always_ff _ _ }
|
|
|
|
|
"always_latch" { Token KW_always_latch _ _ }
|
2019-02-08 05:49:12 +01:00
|
|
|
"assign" { Token KW_assign _ _ }
|
|
|
|
|
"begin" { Token KW_begin _ _ }
|
|
|
|
|
"case" { Token KW_case _ _ }
|
2019-02-23 21:10:25 +01:00
|
|
|
"casex" { Token KW_casex _ _ }
|
2019-02-08 05:49:12 +01:00
|
|
|
"casez" { Token KW_casez _ _ }
|
|
|
|
|
"default" { Token KW_default _ _ }
|
|
|
|
|
"else" { Token KW_else _ _ }
|
|
|
|
|
"end" { Token KW_end _ _ }
|
|
|
|
|
"endcase" { Token KW_endcase _ _ }
|
2019-02-15 05:29:42 +01:00
|
|
|
"endfunction" { Token KW_endfunction _ _ }
|
2019-02-18 00:33:20 +01:00
|
|
|
"endgenerate" { Token KW_endgenerate _ _ }
|
2019-02-08 05:49:12 +01:00
|
|
|
"endmodule" { Token KW_endmodule _ _ }
|
2019-02-24 03:24:13 +01:00
|
|
|
"enum" { Token KW_enum _ _ }
|
2019-02-15 05:29:42 +01:00
|
|
|
"function" { Token KW_function _ _ }
|
2019-02-08 05:49:12 +01:00
|
|
|
"for" { Token KW_for _ _ }
|
2019-02-18 00:33:20 +01:00
|
|
|
"generate" { Token KW_generate _ _ }
|
|
|
|
|
"genvar" { Token KW_genvar _ _ }
|
2019-02-08 05:49:12 +01:00
|
|
|
"if" { Token KW_if _ _ }
|
|
|
|
|
"initial" { Token KW_initial _ _ }
|
|
|
|
|
"inout" { Token KW_inout _ _ }
|
|
|
|
|
"input" { Token KW_input _ _ }
|
|
|
|
|
"integer" { Token KW_integer _ _ }
|
|
|
|
|
"localparam" { Token KW_localparam _ _ }
|
2019-02-18 05:39:01 +01:00
|
|
|
"logic" { Token KW_logic _ _ }
|
2019-02-08 05:49:12 +01:00
|
|
|
"module" { Token KW_module _ _ }
|
|
|
|
|
"negedge" { Token KW_negedge _ _ }
|
|
|
|
|
"or" { Token KW_or _ _ }
|
|
|
|
|
"output" { Token KW_output _ _ }
|
2019-03-02 02:26:44 +01:00
|
|
|
"packed" { Token KW_packed _ _ }
|
2019-02-08 05:49:12 +01:00
|
|
|
"parameter" { Token KW_parameter _ _ }
|
|
|
|
|
"posedge" { Token KW_posedge _ _ }
|
|
|
|
|
"reg" { Token KW_reg _ _ }
|
2019-03-02 02:26:44 +01:00
|
|
|
"struct" { Token KW_struct _ _ }
|
2019-02-18 09:59:17 +01:00
|
|
|
"typedef" { Token KW_typedef _ _ }
|
2019-02-23 21:10:25 +01:00
|
|
|
"unique" { Token KW_unique _ _ }
|
2019-02-08 05:49:12 +01:00
|
|
|
"wire" { Token KW_wire _ _ }
|
|
|
|
|
|
|
|
|
|
simpleIdentifier { Token Id_simple _ _ }
|
|
|
|
|
escapedIdentifier { Token Id_escaped _ _ }
|
|
|
|
|
systemIdentifier { Token Id_system _ _ }
|
|
|
|
|
number { Token Lit_number _ _ }
|
|
|
|
|
string { Token Lit_string _ _ }
|
|
|
|
|
|
|
|
|
|
"(" { Token Sym_paren_l _ _ }
|
|
|
|
|
")" { Token Sym_paren_r _ _ }
|
|
|
|
|
"[" { Token Sym_brack_l _ _ }
|
|
|
|
|
"]" { Token Sym_brack_r _ _ }
|
|
|
|
|
"{" { Token Sym_brace_l _ _ }
|
|
|
|
|
"}" { Token Sym_brace_r _ _ }
|
|
|
|
|
"~" { Token Sym_tildy _ _ }
|
|
|
|
|
"!" { Token Sym_bang _ _ }
|
|
|
|
|
"@" { Token Sym_at _ _ }
|
|
|
|
|
"#" { Token Sym_pound _ _ }
|
|
|
|
|
"%" { Token Sym_percent _ _ }
|
|
|
|
|
"^" { Token Sym_hat _ _ }
|
|
|
|
|
"&" { Token Sym_amp _ _ }
|
|
|
|
|
"|" { Token Sym_bar _ _ }
|
|
|
|
|
"*" { Token Sym_aster _ _ }
|
|
|
|
|
"." { Token Sym_dot _ _ }
|
|
|
|
|
"," { Token Sym_comma _ _ }
|
|
|
|
|
":" { Token Sym_colon _ _ }
|
|
|
|
|
";" { Token Sym_semi _ _ }
|
|
|
|
|
"=" { Token Sym_eq _ _ }
|
|
|
|
|
"<" { Token Sym_lt _ _ }
|
|
|
|
|
">" { Token Sym_gt _ _ }
|
|
|
|
|
"+" { Token Sym_plus _ _ }
|
|
|
|
|
"-" { Token Sym_dash _ _ }
|
|
|
|
|
"?" { Token Sym_question _ _ }
|
|
|
|
|
"/" { Token Sym_slash _ _ }
|
|
|
|
|
"$" { Token Sym_dollar _ _ }
|
|
|
|
|
"'" { Token Sym_s_quote _ _ }
|
|
|
|
|
"~&" { Token Sym_tildy_amp _ _ }
|
|
|
|
|
"~|" { Token Sym_tildy_bar _ _ }
|
|
|
|
|
"~^" { Token Sym_tildy_hat _ _ }
|
|
|
|
|
"^~" { Token Sym_hat_tildy _ _ }
|
|
|
|
|
"==" { Token Sym_eq_eq _ _ }
|
|
|
|
|
"!=" { Token Sym_bang_eq _ _ }
|
|
|
|
|
"&&" { Token Sym_amp_amp _ _ }
|
|
|
|
|
"||" { Token Sym_bar_bar _ _ }
|
|
|
|
|
"**" { Token Sym_aster_aster _ _ }
|
|
|
|
|
"<=" { Token Sym_lt_eq _ _ }
|
|
|
|
|
">=" { Token Sym_gt_eq _ _ }
|
|
|
|
|
">>" { Token Sym_gt_gt _ _ }
|
|
|
|
|
"<<" { Token Sym_lt_lt _ _ }
|
|
|
|
|
"++" { Token Sym_plus_plus _ _ }
|
|
|
|
|
"--" { Token Sym_dash_dash _ _ }
|
|
|
|
|
"+=" { Token Sym_plus_eq _ _ }
|
|
|
|
|
"-=" { Token Sym_dash_eq _ _ }
|
|
|
|
|
"*=" { Token Sym_aster_eq _ _ }
|
|
|
|
|
"/=" { Token Sym_slash_eq _ _ }
|
|
|
|
|
"%=" { Token Sym_percent_eq _ _ }
|
|
|
|
|
"&=" { Token Sym_amp_eq _ _ }
|
|
|
|
|
"|=" { Token Sym_bar_eq _ _ }
|
|
|
|
|
"^=" { Token Sym_hat_eq _ _ }
|
|
|
|
|
"+:" { Token Sym_plus_colon _ _ }
|
|
|
|
|
"-:" { Token Sym_dash_colon _ _ }
|
|
|
|
|
"::" { Token Sym_colon_colon _ _ }
|
|
|
|
|
".*" { Token Sym_dot_aster _ _ }
|
|
|
|
|
"->" { Token Sym_dash_gt _ _ }
|
|
|
|
|
":=" { Token Sym_colon_eq _ _ }
|
|
|
|
|
":/" { Token Sym_colon_slash _ _ }
|
|
|
|
|
"##" { Token Sym_pound_pound _ _ }
|
|
|
|
|
"[*" { Token Sym_brack_l_aster _ _ }
|
|
|
|
|
"[=" { Token Sym_brack_l_eq _ _ }
|
|
|
|
|
"=>" { Token Sym_eq_gt _ _ }
|
|
|
|
|
"@*" { Token Sym_at_aster _ _ }
|
|
|
|
|
"(*" { Token Sym_paren_l_aster _ _ }
|
|
|
|
|
"*)" { Token Sym_aster_paren_r _ _ }
|
|
|
|
|
"*>" { Token Sym_aster_gt _ _ }
|
|
|
|
|
"===" { Token Sym_eq_eq_eq _ _ }
|
|
|
|
|
"!==" { Token Sym_bang_eq_eq _ _ }
|
|
|
|
|
"=?=" { Token Sym_eq_question_eq _ _ }
|
|
|
|
|
"!?=" { Token Sym_bang_question_eq _ _ }
|
|
|
|
|
">>>" { Token Sym_gt_gt_gt _ _ }
|
|
|
|
|
"<<<" { Token Sym_lt_lt_lt _ _ }
|
|
|
|
|
"<<=" { Token Sym_lt_lt_eq _ _ }
|
|
|
|
|
">>=" { Token Sym_gt_gt_eq _ _ }
|
|
|
|
|
"|->" { Token Sym_bar_dash_gt _ _ }
|
|
|
|
|
"|=>" { Token Sym_bar_eq_gt _ _ }
|
|
|
|
|
"[->" { Token Sym_brack_l_dash_gt _ _ }
|
|
|
|
|
"@@(" { Token Sym_at_at_paren_l _ _ }
|
|
|
|
|
"(*)" { Token Sym_paren_l_aster_paren_r _ _ }
|
|
|
|
|
"->>" { Token Sym_dash_gt_gt _ _ }
|
|
|
|
|
"&&&" { Token Sym_amp_amp_amp _ _ }
|
|
|
|
|
"<<<=" { Token Sym_lt_lt_lt_eq _ _ }
|
|
|
|
|
">>>=" { Token Sym_gt_gt_gt_eq _ _ }
|
|
|
|
|
|
|
|
|
|
%nonassoc NoElse
|
|
|
|
|
%nonassoc "else"
|
|
|
|
|
%right "?" ":"
|
|
|
|
|
%left "||"
|
|
|
|
|
%left "&&"
|
|
|
|
|
%left "|" "~|"
|
|
|
|
|
%left "^" "^~"
|
|
|
|
|
%left "&" "~&"
|
|
|
|
|
%left "==" "!=" "===" "!=="
|
|
|
|
|
%left "<" "<=" ">" ">="
|
2019-02-18 02:52:01 +01:00
|
|
|
%left "<<" ">>" "<<<" ">>>"
|
2019-02-08 05:49:12 +01:00
|
|
|
%left "+" "-"
|
|
|
|
|
%left "*" "/" "%"
|
2019-02-10 23:46:18 +01:00
|
|
|
%left UPlus UMinus "!" "~" RedOps
|
2019-03-02 02:26:44 +01:00
|
|
|
%left "."
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
2019-02-10 00:35:15 +01:00
|
|
|
opt(p) :: { Maybe a }
|
|
|
|
|
: p { Just $1 }
|
|
|
|
|
| { Nothing }
|
|
|
|
|
|
2019-02-18 09:59:17 +01:00
|
|
|
Descriptions :: { [Description] }
|
2019-02-10 00:35:15 +01:00
|
|
|
: {- empty -} { [] }
|
2019-02-18 09:59:17 +01:00
|
|
|
| Descriptions Description { $1 ++ [$2] }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
2019-02-18 09:59:17 +01:00
|
|
|
Description :: { Description }
|
|
|
|
|
: Module opt(";") { $1 }
|
|
|
|
|
| Typedef opt(";") { $1 }
|
|
|
|
|
|
|
|
|
|
Typedef :: { Description }
|
|
|
|
|
: "typedef" Type Identifier ";" { Typedef $2 $3 }
|
|
|
|
|
|
2019-02-24 03:24:13 +01:00
|
|
|
TypeNonAlias :: { Type }
|
|
|
|
|
: "wire" Dimensions { Wire $2 }
|
|
|
|
|
| "reg" Dimensions { Reg $2 }
|
|
|
|
|
| "logic" Dimensions { Logic $2 }
|
2019-03-02 02:26:44 +01:00
|
|
|
| "enum" opt(Type) "{" EnumItems "}" Dimensions { Enum $2 $4 $6 }
|
|
|
|
|
| "struct" Packed "{" StructItems "}" Dimensions { Struct $2 $4 $6 }
|
2019-02-18 09:59:17 +01:00
|
|
|
Type :: { Type }
|
2019-02-24 03:24:13 +01:00
|
|
|
: TypeNonAlias { $1 }
|
2019-02-20 22:03:04 +01:00
|
|
|
| Identifier Dimensions { Alias $1 $2 }
|
2019-02-18 09:59:17 +01:00
|
|
|
|
2019-03-02 02:26:44 +01:00
|
|
|
EnumItems :: { [(Identifier, Maybe Expr)] }
|
|
|
|
|
: VariablePortIdentifiers { $1 }
|
|
|
|
|
|
|
|
|
|
StructItems :: { [(Type, Identifier)] }
|
|
|
|
|
: StructItem { [$1] }
|
|
|
|
|
| StructItems StructItem { $1 ++ [$2] }
|
|
|
|
|
StructItem :: { (Type, Identifier) }
|
|
|
|
|
: Type Identifier ";" { ($1, $2) }
|
|
|
|
|
|
|
|
|
|
Packed :: { Bool }
|
|
|
|
|
: "packed" { True }
|
|
|
|
|
| {- empty -} { False }
|
|
|
|
|
|
2019-02-18 09:59:17 +01:00
|
|
|
Module :: { Description }
|
|
|
|
|
: "module" Identifier Params ";" ModuleItems "endmodule" { Module $2 [] ($3 ++ $5) }
|
|
|
|
|
| "module" Identifier Params PortNames ";" ModuleItems "endmodule" { Module $2 $4 ($3 ++ $6) }
|
|
|
|
|
| "module" Identifier Params PortDecls ";" ModuleItems "endmodule" { Module $2 (getPortNames $4) ($3 ++ $4 ++ $6) }
|
2019-02-11 20:07:46 +01:00
|
|
|
|
|
|
|
|
Params :: { [ModuleItem] }
|
|
|
|
|
: {- empty -} { [] }
|
|
|
|
|
| "#" "(" ParamDecls { $3 }
|
|
|
|
|
ParamDecls :: { [ModuleItem] }
|
|
|
|
|
: ParamDecl(")") { $1 }
|
|
|
|
|
| ParamDecl(",") ParamDecls { $1 ++ $2 }
|
|
|
|
|
ParamDecl(delim) :: { [ModuleItem] }
|
2019-02-24 09:06:40 +01:00
|
|
|
: "parameter" ParamType DeclAsgns delim { map (MIDecl . (uncurry $ Parameter $2)) $3 }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
Identifier :: { Identifier }
|
2019-02-10 00:35:15 +01:00
|
|
|
: simpleIdentifier { tokenString $1 }
|
|
|
|
|
| escapedIdentifier { tokenString $1 }
|
|
|
|
|
| systemIdentifier { tokenString $1 }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
2019-02-10 00:35:15 +01:00
|
|
|
Identifiers :: { [Identifier] }
|
|
|
|
|
: Identifier { [$1] }
|
|
|
|
|
| Identifiers "," Identifier { $1 ++ [$3] }
|
|
|
|
|
|
|
|
|
|
PortNames :: { [Identifier] }
|
|
|
|
|
: "(" Identifiers ")" { $2 }
|
|
|
|
|
|
|
|
|
|
-- abuses delimiter propogation hack to avoid conflicts
|
|
|
|
|
PortDecls :: { [ModuleItem] }
|
|
|
|
|
: "(" PortDeclsFollow { $2 }
|
|
|
|
|
PortDeclsFollow :: { [ModuleItem] }
|
|
|
|
|
: ")" { [] }
|
|
|
|
|
| PortDecl(")") { $1 }
|
|
|
|
|
| PortDecl(",") PortDeclsFollow { $1 ++ $2 }
|
|
|
|
|
PortDecl(delim) :: { [ModuleItem] }
|
2019-03-02 02:26:44 +01:00
|
|
|
: Direction TypedVariablePortIdentifiers(delim) { portDeclToModuleItems $1 $2 }
|
|
|
|
|
|
2019-02-10 00:35:15 +01:00
|
|
|
VariablePortIdentifiers :: { [(Identifier, Maybe Expr)] }
|
|
|
|
|
: VariablePortIdentifier { [$1] }
|
|
|
|
|
| VariablePortIdentifiers "," VariablePortIdentifier { $1 ++ [$3] }
|
|
|
|
|
VariablePortIdentifier :: { (Identifier, Maybe Expr) }
|
|
|
|
|
: Identifier { ($1, Nothing) }
|
|
|
|
|
| Identifier "=" Expr { ($1, Just $3) }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
2019-03-02 02:26:44 +01:00
|
|
|
-- Note that this allows for things like `input reg` which are not valid.
|
|
|
|
|
TypedVariablePortIdentifiers(delim) :: { (Type, [PortBinding]) }
|
|
|
|
|
: TypeNonAlias VariablePortIdentifiers delim { ($1, $2) }
|
|
|
|
|
| Identifier DimensionsNonEmpty VariablePortIdentifiers delim { (Alias $1 $2, $3) }
|
|
|
|
|
| Identifier VariablePortIdentifiers delim { (Alias $1 [], $2) }
|
|
|
|
|
| DimensionsNonEmpty VariablePortIdentifiers delim { (Implicit $1, $2) }
|
|
|
|
|
| VariablePortIdentifiers delim { (Implicit [], $1) }
|
|
|
|
|
Direction :: { Direction }
|
|
|
|
|
: "inout" { Inout }
|
|
|
|
|
| "input" { Input }
|
|
|
|
|
| "output" { Output }
|
|
|
|
|
|
2019-02-08 05:49:12 +01:00
|
|
|
ModuleItems :: { [ModuleItem] }
|
2019-02-11 21:16:25 +01:00
|
|
|
: {- empty -} { [] }
|
|
|
|
|
| ModuleItems ModuleItem { $1 ++ $2 }
|
2019-02-09 23:35:31 +01:00
|
|
|
|
|
|
|
|
ModuleItem :: { [ModuleItem] }
|
2019-02-15 05:29:42 +01:00
|
|
|
: PortDecl(";") { $1 }
|
2019-02-24 09:06:40 +01:00
|
|
|
| Identifier VariableIdentifiers ";" { map (\(x, a, e) -> MIDecl $ Variable Local (Alias $1 []) x a e) $2 }
|
|
|
|
|
| Identifier DimensionsNonEmpty VariableIdentifiers ";" { map (\(x, a, e) -> MIDecl $ Variable Local (Alias $1 $2) x a e) $3 }
|
|
|
|
|
| TypeNonAlias VariableIdentifiers ";" { map (\(x, a, e) -> MIDecl $ Variable Local $1 x a e) $2 }
|
|
|
|
|
| Declaration { map MIDecl $1 }
|
2019-02-11 21:16:25 +01:00
|
|
|
| "assign" LHS "=" Expr ";" { [Assign $2 $4] }
|
2019-02-18 06:26:43 +01:00
|
|
|
| AlwaysKW Stmt { [AlwaysC $1 $2] }
|
2019-02-18 09:59:17 +01:00
|
|
|
| Identifier ModuleInstantiations ";" { map (uncurry $ Instance $1 []) $2 }
|
2019-02-18 00:50:56 +01:00
|
|
|
| Identifier ParameterBindings ModuleInstantiations ";" { map (uncurry $ Instance $1 $2) $3 }
|
2019-02-24 09:06:40 +01:00
|
|
|
| "function" ParamType Identifier FunctionItems Stmt "endfunction" { [Function $2 $3 $4 $5] }
|
2019-02-18 00:33:20 +01:00
|
|
|
| "genvar" Identifiers ";" { map Genvar $2 }
|
|
|
|
|
| "generate" GenItems "endgenerate" { [Generate $2] }
|
2019-02-15 05:29:42 +01:00
|
|
|
|
2019-02-18 06:26:43 +01:00
|
|
|
AlwaysKW :: { AlwaysKW }
|
|
|
|
|
: "always" { Always }
|
|
|
|
|
| "always_comb" { AlwaysComb }
|
|
|
|
|
| "always_ff" { AlwaysFF }
|
|
|
|
|
| "always_latch" { AlwaysLatch }
|
|
|
|
|
|
2019-02-20 21:22:26 +01:00
|
|
|
ModuleInstantiations :: { [(Identifier, Maybe [PortBinding])] }
|
2019-02-18 00:50:56 +01:00
|
|
|
: ModuleInstantiation { [$1] }
|
|
|
|
|
| ModuleInstantiations "," ModuleInstantiation { $1 ++ [$3] }
|
2019-02-20 21:22:26 +01:00
|
|
|
ModuleInstantiation :: { (Identifier, Maybe [PortBinding]) }
|
|
|
|
|
: Identifier "(" Bindings ")" { ($1, Just $3) }
|
|
|
|
|
| Identifier "(" ".*" ")" { ($1, Nothing) }
|
2019-02-18 00:50:56 +01:00
|
|
|
|
2019-02-24 09:06:40 +01:00
|
|
|
FunctionItems :: { [Decl] }
|
|
|
|
|
: "(" FunctionPortList ";" BlockItemDeclarations { $2 ++ $4 }
|
|
|
|
|
| "(" FunctionPortList ";" { $2 }
|
2019-02-15 05:29:42 +01:00
|
|
|
| ";" FunctionItemDeclarations { $2 }
|
2019-02-24 09:06:40 +01:00
|
|
|
FunctionPortList :: { [Decl] }
|
2019-02-15 05:29:42 +01:00
|
|
|
: FunctionInputDeclaration(")") { $1 }
|
|
|
|
|
| FunctionInputDeclaration(",") FunctionPortList { $1 ++ $2 }
|
2019-02-24 09:06:40 +01:00
|
|
|
FunctionItemDeclarations :: { [Decl] }
|
2019-02-15 05:29:42 +01:00
|
|
|
: FunctionItemDeclaration { $1 }
|
|
|
|
|
| FunctionItemDeclarations FunctionItemDeclaration { $1 ++ $2 }
|
2019-02-24 09:06:40 +01:00
|
|
|
FunctionItemDeclaration :: { [Decl] }
|
|
|
|
|
: BlockItemDeclaration { $1 }
|
|
|
|
|
| FunctionInputDeclaration(";") { $1 }
|
|
|
|
|
FunctionInputDeclaration(delim) :: { [Decl] }
|
|
|
|
|
: "input" Dimensions Identifiers delim { map (\x -> Variable Input (Implicit $2) x [] Nothing) $3 }
|
|
|
|
|
| "input" "reg" Dimensions Identifiers delim { map (\x -> Variable Input (Reg $3) x [] Nothing) $4 }
|
|
|
|
|
| "input" "integer" Identifiers delim { map (\x -> Variable Input IntegerT x [] Nothing) $3 }
|
|
|
|
|
|
|
|
|
|
Declaration :: { [Decl] }
|
|
|
|
|
: "parameter" ParamType DeclAsgns ";" { map (uncurry $ Parameter $2) $3 }
|
|
|
|
|
| "localparam" ParamType DeclAsgns ";" { map (uncurry $ Localparam $2) $3 }
|
|
|
|
|
| "integer" VariableIdentifiers ";" { map (\(x, a, e) -> Variable Local IntegerT x a e) $2 }
|
|
|
|
|
|
|
|
|
|
ParamType :: { Type }
|
|
|
|
|
: Dimensions { Implicit $1 }
|
|
|
|
|
| "integer" { IntegerT }
|
2019-02-11 21:16:25 +01:00
|
|
|
|
|
|
|
|
EventControl :: { Sense }
|
|
|
|
|
: "@" "(" Sense ")" { $3 }
|
|
|
|
|
| "@" "(" "*" ")" { SenseStar }
|
2019-02-22 19:55:48 +01:00
|
|
|
| "@" "(*)" { SenseStar }
|
2019-02-11 21:16:25 +01:00
|
|
|
| "@" "*" { SenseStar }
|
|
|
|
|
| "@*" { SenseStar }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
2019-02-24 09:06:40 +01:00
|
|
|
VariableIdentifiers :: { [(Identifier, [Range], Maybe Expr)] }
|
2019-02-11 19:47:56 +01:00
|
|
|
: VariableType { [$1] }
|
|
|
|
|
| VariableIdentifiers "," VariableType { $1 ++ [$3] }
|
2019-02-24 09:06:40 +01:00
|
|
|
VariableType :: { (Identifier, [Range], Maybe Expr) }
|
|
|
|
|
: Identifier Dimensions { ($1, $2, Nothing) }
|
|
|
|
|
| Identifier Dimensions "=" Expr { ($1, $2, Just $4) }
|
2019-02-11 19:47:56 +01:00
|
|
|
|
|
|
|
|
Dimensions :: { [Range] }
|
2019-02-20 22:03:04 +01:00
|
|
|
: {- empty -} { [] }
|
|
|
|
|
| DimensionsNonEmpty { $1 }
|
|
|
|
|
DimensionsNonEmpty :: { [Range] }
|
|
|
|
|
: Range { [$1] }
|
|
|
|
|
| DimensionsNonEmpty Range { $1 ++ [$2] }
|
2019-02-11 19:47:56 +01:00
|
|
|
|
2019-02-11 08:12:52 +01:00
|
|
|
DeclAsgns :: { [(Identifier, Expr)] }
|
|
|
|
|
: DeclAsgn { [$1] }
|
2019-02-11 20:07:46 +01:00
|
|
|
| DeclAsgns "," DeclAsgn { $1 ++ [$3] }
|
2019-02-11 08:12:52 +01:00
|
|
|
DeclAsgn :: { (Identifier, Expr) }
|
|
|
|
|
: Identifier "=" Expr { ($1, $3) }
|
|
|
|
|
|
2019-02-08 05:49:12 +01:00
|
|
|
Range :: { Range }
|
2019-02-11 21:16:25 +01:00
|
|
|
: "[" Expr ":" Expr "]" { ($2, $4) }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
LHS :: { LHS }
|
|
|
|
|
: Identifier { LHS $1 }
|
|
|
|
|
| Identifier Range { LHSRange $1 $2 }
|
|
|
|
|
| Identifier "[" Expr "]" { LHSBit $1 $3 }
|
|
|
|
|
| "{" LHSs "}" { LHSConcat $2 }
|
|
|
|
|
|
|
|
|
|
LHSs :: { [LHS] }
|
2019-02-08 05:58:34 +01:00
|
|
|
: LHS { [$1] }
|
2019-02-08 05:49:12 +01:00
|
|
|
| LHSs "," LHS { $1 ++ [$3] }
|
|
|
|
|
|
|
|
|
|
Sense :: { Sense }
|
|
|
|
|
: Sense1 { $1 }
|
|
|
|
|
| Sense "or" Sense1 { SenseOr $1 $3 }
|
|
|
|
|
|
|
|
|
|
Sense1 :: { Sense }
|
|
|
|
|
: LHS { Sense $1 }
|
|
|
|
|
| "posedge" LHS { SensePosedge $2 }
|
|
|
|
|
| "negedge" LHS { SenseNegedge $2 }
|
|
|
|
|
|
|
|
|
|
Bindings :: { [(Identifier, Maybe Expr)] }
|
2019-02-18 00:50:56 +01:00
|
|
|
: {- empty -} { [] }
|
|
|
|
|
| BindingsNonEmpty { $1 }
|
|
|
|
|
BindingsNonEmpty :: { [(Identifier, Maybe Expr)] }
|
|
|
|
|
: Binding { [$1] }
|
|
|
|
|
| Binding "," BindingsNonEmpty { $1 : $3}
|
2019-02-08 05:49:12 +01:00
|
|
|
Binding :: { (Identifier, Maybe Expr) }
|
2019-02-24 09:06:40 +01:00
|
|
|
: "." Identifier "(" opt(Expr) ")" { ($2, $4) }
|
2019-02-18 00:50:56 +01:00
|
|
|
| "." Identifier { ($2, Just $ Ident $2) }
|
|
|
|
|
| Expr { ("", Just $1) }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
ParameterBindings :: { [(Identifier, Maybe Expr)] }
|
2019-02-18 09:59:17 +01:00
|
|
|
: "#" "(" BindingsNonEmpty ")" { $3 }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
Stmts :: { [Stmt] }
|
2019-02-11 21:16:25 +01:00
|
|
|
: {- empty -} { [] }
|
|
|
|
|
| Stmts Stmt { $1 ++ [$2] }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
Stmt :: { Stmt }
|
2019-02-11 20:46:09 +01:00
|
|
|
: ";" { Null }
|
2019-02-15 05:29:42 +01:00
|
|
|
| "begin" Stmts "end" { Block Nothing $2 }
|
|
|
|
|
| "begin" ":" Identifier Stmts "end" { Block (Just ($3, [])) $4 }
|
|
|
|
|
| "begin" ":" Identifier BlockItemDeclarations Stmts "end" { Block (Just ($3, $4)) $5 }
|
2019-02-11 20:46:09 +01:00
|
|
|
| "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 }
|
2019-02-24 09:06:40 +01:00
|
|
|
| LHS "=" Expr ";" { AsgnBlk $1 $3 }
|
|
|
|
|
| LHS "<=" Expr ";" { Asgn $1 $3 }
|
2019-02-23 21:10:25 +01:00
|
|
|
| CaseKW "(" Expr ")" Cases opt(CaseDefault) "endcase" { Case $1 $3 $5 $6 }
|
2019-02-18 06:26:43 +01:00
|
|
|
| EventControl Stmt { Timing $1 $2 }
|
2019-02-11 20:46:09 +01:00
|
|
|
|
2019-02-24 09:06:40 +01:00
|
|
|
BlockItemDeclarations :: { [Decl] }
|
2019-02-15 05:29:42 +01:00
|
|
|
: BlockItemDeclaration { $1 }
|
|
|
|
|
| BlockItemDeclarations BlockItemDeclaration { $1 ++ $2 }
|
|
|
|
|
|
2019-02-24 09:06:40 +01:00
|
|
|
BlockItemDeclaration :: { [Decl] }
|
|
|
|
|
: "reg" Dimensions BlockVariableIdentifiers ";" { map (\(x, rs) -> Variable Local (Reg $2) x rs Nothing) $3 }
|
|
|
|
|
| Declaration { $1 }
|
2019-02-15 05:29:42 +01:00
|
|
|
BlockVariableIdentifiers :: { [(Identifier, [Range])] }
|
|
|
|
|
: BlockVariableType { [$1] }
|
|
|
|
|
| BlockVariableIdentifiers "," BlockVariableType { $1 ++ [$3] }
|
|
|
|
|
BlockVariableType :: { (Identifier, [Range]) }
|
2019-02-20 22:03:04 +01:00
|
|
|
: Identifier Dimensions { ($1, $2) }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
2019-02-23 21:10:25 +01:00
|
|
|
CaseKW :: { CaseKW }
|
|
|
|
|
-- We just drop the unique keyword, for now. In the future, we should add it
|
|
|
|
|
-- to the AST and add a conversion phase for removing it.
|
|
|
|
|
: opt("unique") "case" { CaseN }
|
|
|
|
|
| opt("unique") "casex" { CaseX }
|
|
|
|
|
| opt("unique") "casez" { CaseZ }
|
|
|
|
|
|
2019-02-08 05:49:12 +01:00
|
|
|
Cases :: { [Case] }
|
2019-02-18 00:33:20 +01:00
|
|
|
: {- empty -} { [] }
|
|
|
|
|
| Cases Case { $1 ++ [$2] }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
Case :: { Case }
|
2019-02-18 00:33:20 +01:00
|
|
|
: Exprs ":" Stmt { ($1, $3) }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
2019-02-18 00:33:20 +01:00
|
|
|
CaseDefault :: { Stmt }
|
|
|
|
|
: "default" opt(":") Stmt { $3 }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
2019-02-17 20:54:12 +01:00
|
|
|
Number :: { String }
|
|
|
|
|
: number { tokenString $1 }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
String :: { String }
|
2019-02-24 09:06:40 +01:00
|
|
|
: string { tail $ init $ tokenString $1 }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
CallArgs :: { [Expr] }
|
2019-02-18 03:17:00 +01:00
|
|
|
: Expr { [$1] }
|
|
|
|
|
| CallArgs "," Expr { $1 ++ [$3] }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
Exprs :: { [Expr] }
|
|
|
|
|
: Expr { [$1] }
|
|
|
|
|
| Exprs "," Expr { $1 ++ [$3] }
|
|
|
|
|
|
|
|
|
|
Expr :: { Expr }
|
|
|
|
|
: "(" Expr ")" { $2 }
|
|
|
|
|
| String { String $1 }
|
|
|
|
|
| Number { Number $1 }
|
2019-02-18 03:17:00 +01:00
|
|
|
| Identifier "(" CallArgs ")" { Call $1 $3 }
|
2019-02-08 05:49:12 +01:00
|
|
|
| Identifier { Ident $1 }
|
|
|
|
|
| Identifier Range { IdentRange $1 $2 }
|
|
|
|
|
| Identifier "[" Expr "]" { IdentBit $1 $3 }
|
|
|
|
|
| "{" Expr "{" Exprs "}" "}" { Repeat $2 $4 }
|
|
|
|
|
| "{" Exprs "}" { Concat $2 }
|
|
|
|
|
| Expr "?" Expr ":" Expr { Mux $1 $3 $5 }
|
|
|
|
|
| Expr "||" Expr { BinOp Or $1 $3 }
|
|
|
|
|
| Expr "&&" Expr { BinOp And $1 $3 }
|
|
|
|
|
| Expr "|" Expr { BinOp BWOr $1 $3 }
|
|
|
|
|
| Expr "^" Expr { BinOp BWXor $1 $3 }
|
|
|
|
|
| Expr "&" Expr { BinOp BWAnd $1 $3 }
|
|
|
|
|
| Expr "==" Expr { BinOp Eq $1 $3 }
|
|
|
|
|
| Expr "!=" Expr { BinOp Ne $1 $3 }
|
|
|
|
|
| Expr "<" Expr { BinOp Lt $1 $3 }
|
|
|
|
|
| Expr "<=" Expr { BinOp Le $1 $3 }
|
|
|
|
|
| Expr ">" Expr { BinOp Gt $1 $3 }
|
|
|
|
|
| Expr ">=" Expr { BinOp Ge $1 $3 }
|
|
|
|
|
| Expr "<<" Expr { BinOp ShiftL $1 $3 }
|
|
|
|
|
| Expr ">>" Expr { BinOp ShiftR $1 $3 }
|
|
|
|
|
| Expr "+" Expr { BinOp Add $1 $3 }
|
|
|
|
|
| Expr "-" Expr { BinOp Sub $1 $3 }
|
|
|
|
|
| Expr "*" Expr { BinOp Mul $1 $3 }
|
2019-02-10 23:46:18 +01:00
|
|
|
| Expr "/" Expr { BinOp Div $1 $3 }
|
2019-02-08 05:49:12 +01:00
|
|
|
| Expr "%" Expr { BinOp Mod $1 $3 }
|
2019-02-18 02:52:01 +01:00
|
|
|
| Expr "<<<" Expr { BinOp ShiftAL $1 $3 }
|
|
|
|
|
| Expr ">>>" Expr { BinOp ShiftAR $1 $3 }
|
2019-02-08 05:49:12 +01:00
|
|
|
| "!" Expr { UniOp Not $2 }
|
|
|
|
|
| "~" Expr { UniOp BWNot $2 }
|
|
|
|
|
| "+" Expr %prec UPlus { UniOp UAdd $2 }
|
|
|
|
|
| "-" Expr %prec UMinus { UniOp USub $2 }
|
2019-02-10 23:46:18 +01:00
|
|
|
| "&" Expr %prec RedOps { UniOp RedAnd $2 }
|
|
|
|
|
| "~&" Expr %prec RedOps { UniOp RedNand $2 }
|
|
|
|
|
| "|" Expr %prec RedOps { UniOp RedOr $2 }
|
|
|
|
|
| "~|" Expr %prec RedOps { UniOp RedNor $2 }
|
|
|
|
|
| "^" Expr %prec RedOps { UniOp RedXor $2 }
|
|
|
|
|
| "~^" Expr %prec RedOps { UniOp RedXnor $2 }
|
|
|
|
|
| "^~" Expr %prec RedOps { UniOp RedXnor $2 }
|
2019-02-24 03:24:13 +01:00
|
|
|
| Type "'" "(" Expr ")" { Cast $1 $4 }
|
2019-03-02 02:26:44 +01:00
|
|
|
| Expr "." Identifier { StructAccess $1 $3 }
|
|
|
|
|
| "'" "{" PatternItems "}" { StructPattern $3 }
|
|
|
|
|
|
|
|
|
|
PatternItems :: { [(Maybe Identifier, Expr)] }
|
|
|
|
|
: PatternNamedItems { map (\(x,e) -> (Just x, e)) $1 }
|
|
|
|
|
| PatternUnnamedItems { zip (repeat Nothing) $1 }
|
|
|
|
|
PatternNamedItems :: { [(Identifier, Expr)] }
|
|
|
|
|
: PatternNamedItem { [$1] }
|
|
|
|
|
| PatternNamedItems "," PatternNamedItem { $1 ++ [$3] }
|
|
|
|
|
PatternNamedItem :: { (Identifier, Expr) }
|
|
|
|
|
: Identifier ":" Expr { ($1, $3) }
|
|
|
|
|
PatternUnnamedItems :: { [Expr] }
|
|
|
|
|
: Exprs { $1 }
|
2019-02-08 05:49:12 +01:00
|
|
|
|
2019-02-18 00:33:20 +01:00
|
|
|
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 }
|
|
|
|
|
|
2019-02-08 05:49:12 +01:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
parseError :: [Token] -> a
|
|
|
|
|
parseError a = case a of
|
|
|
|
|
[] -> error "Parse error: no tokens left to parse."
|
|
|
|
|
Token t s p : _ -> error $ "Parse error: unexpected token '" ++ s ++ "' (" ++ show t ++ ") at " ++ show p ++ "."
|
|
|
|
|
|
2019-03-02 02:26:44 +01:00
|
|
|
portDeclToModuleItems :: Direction -> (Type, [PortBinding]) -> [ModuleItem]
|
|
|
|
|
portDeclToModuleItems dir (t, l) =
|
2019-02-24 09:06:40 +01:00
|
|
|
map (\(x, me) -> MIDecl $ Variable dir t x [] me) l
|
2019-02-09 23:35:31 +01:00
|
|
|
|
2019-02-10 00:35:15 +01:00
|
|
|
getPortNames :: [ModuleItem] -> [Identifier]
|
|
|
|
|
getPortNames items =
|
|
|
|
|
mapMaybe getPortName items
|
2019-02-09 23:35:31 +01:00
|
|
|
where
|
2019-02-10 00:35:15 +01:00
|
|
|
getPortName :: ModuleItem -> Maybe Identifier
|
2019-02-24 09:06:40 +01:00
|
|
|
getPortName (MIDecl (Variable Local _ _ _ _)) = Nothing
|
|
|
|
|
getPortName (MIDecl (Variable _ _ ident _ _)) = Just ident
|
2019-02-10 00:35:15 +01:00
|
|
|
getPortName _ = Nothing
|
|
|
|
|
|
2019-02-18 00:33:20 +01:00
|
|
|
genItemsToGenItem :: [GenItem] -> GenItem
|
|
|
|
|
genItemsToGenItem [] = error "genItemsToGenItem given empty list!"
|
|
|
|
|
genItemsToGenItem [x] = x
|
|
|
|
|
genItemsToGenItem xs = GenBlock Nothing xs
|
|
|
|
|
|
2019-02-08 05:49:12 +01:00
|
|
|
}
|
|
|
|
|
|