diff --git a/src/Convert.hs b/src/Convert.hs index 825670f..85a3356 100644 --- a/src/Convert.hs +++ b/src/Convert.hs @@ -13,10 +13,11 @@ import qualified Convert.AlwaysKW import qualified Convert.CaseKW import qualified Convert.Enum import qualified Convert.Logic -import qualified Convert.Typedef import qualified Convert.PackedArray import qualified Convert.SplitPortDecl import qualified Convert.StarPort +import qualified Convert.Typedef +import qualified Convert.Unique type Phase = AST -> AST @@ -26,6 +27,7 @@ phases YOSYS = , Convert.PackedArray.convert , Convert.StarPort.convert , Convert.Typedef.convert + , Convert.Unique.convert ] phases VTR = (phases YOSYS) ++ diff --git a/src/Convert/CaseKW.hs b/src/Convert/CaseKW.hs index 3fb57e3..af4d875 100644 --- a/src/Convert/CaseKW.hs +++ b/src/Convert/CaseKW.hs @@ -46,8 +46,8 @@ expandExpr _ other = error $ "CaseKW conversion encountered case that was not a -- Note that we don't have to convert the statements within the cases, as the -- conversion template takes care of that for us. convertStmt :: Stmt -> Stmt -convertStmt (Case kw expr cases def) = - Case CaseN expr cases' def +convertStmt (Case u kw expr cases def) = + Case u CaseN expr cases' def where wilds = wildcards kw cases' = map convertCase cases diff --git a/src/Convert/PackedArray.hs b/src/Convert/PackedArray.hs index cc90835..c2de32a 100644 --- a/src/Convert/PackedArray.hs +++ b/src/Convert/PackedArray.hs @@ -158,7 +158,7 @@ unflattener writeToFlatVariant arr (t, (majorHi, majorLo)) = , GenFor (index, majorLo) (BinOp Le (Ident index) majorHi) - (index, BinOp Add (Ident index) (Number "1")) + (index, AsgnOp Add, Number "1") (prefix "unflatten") [ localparam startBit (simplify $ BinOp Add majorLo diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index 10d58de..b47b2d9 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -123,11 +123,11 @@ traverseNestedStmtsM mapper = fullMapper where fullMapper stmt = mapper stmt >>= cs cs (Block decls stmts) = mapM fullMapper stmts >>= return . Block decls - cs (Case kw expr cases def) = do + cs (Case u kw expr cases def) = do caseStmts <- mapM fullMapper $ map snd cases let cases' = zip (map fst cases) caseStmts def' <- maybeDo fullMapper def - return $ Case kw expr cases' def' + return $ Case u kw expr cases' def' cs (AsgnBlk lhs expr) = return $ AsgnBlk lhs expr cs (Asgn lhs expr) = return $ Asgn lhs expr cs (For a b c stmt) = fullMapper stmt >>= return . For a b c @@ -233,10 +233,10 @@ traverseExprsM mapper = moduleItemMapper let Just (name, decls) = header decls' <- mapM declMapper decls return $ Block (Just (name, decls')) stmts - flatStmtMapper (Case kw e cases def) = do + flatStmtMapper (Case u kw e cases def) = do e' <- exprMapper e cases' <- mapM caseMapper cases - return $ Case kw e' cases' def + return $ Case u kw e' cases' def flatStmtMapper (AsgnBlk lhs expr) = exprMapper expr >>= return . AsgnBlk lhs flatStmtMapper (Asgn lhs expr) = diff --git a/src/Convert/Unique.hs b/src/Convert/Unique.hs new file mode 100644 index 0000000..22b990e --- /dev/null +++ b/src/Convert/Unique.hs @@ -0,0 +1,22 @@ +{- sv2v + - Author: Zachary Snow + - + - Conversion for `unique` + - + - This conversion simply drops the `unique` keyword, as it is only used for + - optimization. There is no way to force toolchains which don't support the + - keyword to perform such optimization. + -} + +module Convert.Unique (convert) where + +import Convert.Traverse +import Language.SystemVerilog.AST + +convert :: AST -> AST +convert = traverseDescriptions $ traverseModuleItems $ traverseStmts convertStmt + +convertStmt :: Stmt -> Stmt +convertStmt (Case True kw expr cases def) = + Case False kw expr cases def +convertStmt other = other diff --git a/src/Language/SystemVerilog/AST.hs b/src/Language/SystemVerilog/AST.hs index bfcb082..b593f20 100644 --- a/src/Language/SystemVerilog/AST.hs +++ b/src/Language/SystemVerilog/AST.hs @@ -10,6 +10,7 @@ module Language.SystemVerilog.AST , Expr (..) , UniOp (..) , BinOp (..) + , AsgnOp (..) , Sense (..) , GenItem (..) , AlwaysKW (..) @@ -297,8 +298,13 @@ data BinOp | Le | Gt | Ge + | Pow | ShiftAL | ShiftAR + | TEq + | TNe + | WEq + | WNe deriving (Eq, Ord) instance Show BinOp where @@ -321,8 +327,13 @@ instance Show BinOp where Le -> "<=" Gt -> ">" Ge -> ">=" + Pow -> "**" ShiftAL -> "<<<" ShiftAR -> ">>>" + TEq -> "===" + TNe -> "!==" + WEq -> "==?" + WNe -> "!=?" instance Show Expr where show x = case x of @@ -348,6 +359,15 @@ instance Show Expr where showPatternItem (Nothing, e) = show e showPatternItem (Just n , e) = printf "%s: %s" n (show e) +data AsgnOp + = AsgnOpEq + | AsgnOp BinOp + deriving Eq + +instance Show AsgnOp where + show AsgnOpEq = "=" + show (AsgnOp op) = (show op) ++ "=" + data LHS = LHSIdent Identifier | LHSBit LHS Expr @@ -376,7 +396,7 @@ instance Show CaseKW where data Stmt = Block (Maybe (Identifier, [Decl])) [Stmt] - | Case CaseKW Expr [Case] (Maybe Stmt) + | Case Bool CaseKW Expr [Case] (Maybe Stmt) | For (Identifier, Expr) Expr (Identifier, Expr) Stmt | AsgnBlk LHS Expr | Asgn LHS Expr @@ -398,12 +418,13 @@ instance Show Stmt where extra = case header of Nothing -> "" Just (x, i) -> printf " : %s\n%s" x (block i) - show (Case kw e cs def) = - printf "%s (%s)\n%s%s\nendcase" (show kw) (show e) (indent $ unlines' $ map showCase cs) defStr + show (Case u kw e cs def) = + printf "%s%s (%s)\n%s%s\nendcase" uniqStr (show kw) (show e) (indent $ unlines' $ map showCase cs) defStr where - defStr = case def of - Nothing -> "" - Just c -> printf "\n\tdefault: %s" (show c) + uniqStr = if u then "unique " else "" + defStr = case def of + Nothing -> "" + Just c -> printf "\n\tdefault: %s" (show c) 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 (AsgnBlk v e) = printf "%s = %s;" (show v) (show e) show (Asgn v e) = printf "%s <= %s;" (show v) (show e) @@ -450,7 +471,7 @@ type GenCase = ([Expr], GenItem) data GenItem = GenBlock (Maybe Identifier) [GenItem] | GenCase Expr [GenCase] (Maybe GenItem) - | GenFor (Identifier, Expr) Expr (Identifier, Expr) Identifier [GenItem] + | GenFor (Identifier, Expr) Expr (Identifier, AsgnOp, Expr) Identifier [GenItem] | GenIf Expr GenItem GenItem | GenNull | GenModuleItem ModuleItem @@ -464,7 +485,7 @@ instance Show GenItem where 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) %s" (show e) (show a) show (GenIf e a b ) = printf "if (%s) %s\nelse %s" (show e) (show a) (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 (GenFor (x1, e1) c (x2, o2, e2) x is) = printf "for (%s = %s; %s; %s %s %s) %s" x1 (show e1) (show c) x2 (show o2) (show e2) (show $ GenBlock (Just x) is) show GenNull = ";" show (GenModuleItem item) = show item diff --git a/src/Language/SystemVerilog/Parser/Lex.x b/src/Language/SystemVerilog/Parser/Lex.x index 04fc01f..7007057 100644 --- a/src/Language/SystemVerilog/Parser/Lex.x +++ b/src/Language/SystemVerilog/Parser/Lex.x @@ -56,48 +56,48 @@ tokens :- "always_comb" { tok KW_always_comb } "always_ff" { tok KW_always_ff } "always_latch" { tok KW_always_latch } - "assign" { tok KW_assign } - "automatic" { tok KW_automatic } - "begin" { tok KW_begin } - "case" { tok KW_case } - "casex" { tok KW_casex } - "casez" { tok KW_casez } - "default" { tok KW_default } - "else" { tok KW_else } - "end" { tok KW_end } - "endcase" { tok KW_endcase } - "endmodule" { tok KW_endmodule } - "endfunction" { tok KW_endfunction} - "endgenerate" { tok KW_endgenerate} - "endinterface" { tok KW_endinterface} - "enum" { tok KW_enum } - "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 } - "input" { tok KW_input } - "interface" { tok KW_interface } - "integer" { tok KW_integer } - "localparam" { tok KW_localparam } - "logic" { tok KW_logic } - "module" { tok KW_module } - "modport" { tok KW_modport } - "negedge" { tok KW_negedge } - "or" { tok KW_or } - "output" { tok KW_output } - "packed" { tok KW_packed } - "parameter" { tok KW_parameter } - "posedge" { tok KW_posedge } - "reg" { tok KW_reg } - "return" { tok KW_return } - "static" { tok KW_static } - "struct" { tok KW_struct } - "typedef" { tok KW_typedef } - "unique" { tok KW_unique } - "wire" { tok KW_wire } + "assign" { tok KW_assign } + "automatic" { tok KW_automatic } + "begin" { tok KW_begin } + "case" { tok KW_case } + "casex" { tok KW_casex } + "casez" { tok KW_casez } + "default" { tok KW_default } + "else" { tok KW_else } + "end" { tok KW_end } + "endcase" { tok KW_endcase } + "endmodule" { tok KW_endmodule } + "endfunction" { tok KW_endfunction } + "endgenerate" { tok KW_endgenerate } + "endinterface" { tok KW_endinterface } + "enum" { tok KW_enum } + "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 } + "input" { tok KW_input } + "interface" { tok KW_interface } + "integer" { tok KW_integer } + "localparam" { tok KW_localparam } + "logic" { tok KW_logic } + "module" { tok KW_module } + "modport" { tok KW_modport } + "negedge" { tok KW_negedge } + "or" { tok KW_or } + "output" { tok KW_output } + "packed" { tok KW_packed } + "parameter" { tok KW_parameter } + "posedge" { tok KW_posedge } + "reg" { tok KW_reg } + "return" { tok KW_return } + "static" { tok KW_static } + "struct" { tok KW_struct } + "typedef" { tok KW_typedef } + "unique" { tok KW_unique } + "wire" { tok KW_wire } @simpleIdentifier { tok Id_simple } @escapedIdentifier { tok Id_escaped } @@ -176,8 +176,8 @@ tokens :- "===" { tok Sym_eq_eq_eq } "!==" { tok Sym_bang_eq_eq } - "=?=" { tok Sym_eq_question_eq } - "!?=" { tok Sym_bang_question_eq } + "==?" { tok Sym_eq_eq_question } + "!=?" { tok Sym_bang_eq_question } ">>>" { tok Sym_gt_gt_gt } "<<<" { tok Sym_lt_lt_lt } "<<=" { tok Sym_lt_lt_eq } diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index 5017459..efe2afa 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -21,54 +21,54 @@ import Language.SystemVerilog.Parser.Tokens "always_comb" { Token KW_always_comb _ _ } "always_ff" { Token KW_always_ff _ _ } "always_latch" { Token KW_always_latch _ _ } -"assign" { Token KW_assign _ _ } -"automatic" { Token KW_automatic _ _ } -"begin" { Token KW_begin _ _ } -"case" { Token KW_case _ _ } -"casex" { Token KW_casex _ _ } -"casez" { Token KW_casez _ _ } -"default" { Token KW_default _ _ } -"else" { Token KW_else _ _ } -"end" { Token KW_end _ _ } -"endcase" { Token KW_endcase _ _ } -"endfunction" { Token KW_endfunction _ _ } -"endgenerate" { Token KW_endgenerate _ _ } +"assign" { Token KW_assign _ _ } +"automatic" { Token KW_automatic _ _ } +"begin" { Token KW_begin _ _ } +"case" { Token KW_case _ _ } +"casex" { Token KW_casex _ _ } +"casez" { Token KW_casez _ _ } +"default" { Token KW_default _ _ } +"else" { Token KW_else _ _ } +"end" { Token KW_end _ _ } +"endcase" { Token KW_endcase _ _ } +"endfunction" { Token KW_endfunction _ _ } +"endgenerate" { Token KW_endgenerate _ _ } "endinterface" { Token KW_endinterface _ _ } -"endmodule" { Token KW_endmodule _ _ } -"enum" { Token KW_enum _ _ } -"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 _ _ } -"input" { Token KW_input _ _ } -"integer" { Token KW_integer _ _ } -"interface" { Token KW_interface _ _ } -"localparam" { Token KW_localparam _ _ } -"logic" { Token KW_logic _ _ } -"module" { Token KW_module _ _ } -"modport" { Token KW_modport _ _ } -"negedge" { Token KW_negedge _ _ } -"or" { Token KW_or _ _ } -"output" { Token KW_output _ _ } -"packed" { Token KW_packed _ _ } -"parameter" { Token KW_parameter _ _ } -"posedge" { Token KW_posedge _ _ } -"reg" { Token KW_reg _ _ } -"return" { Token KW_return _ _ } -"static" { Token KW_static _ _ } -"struct" { Token KW_struct _ _ } -"typedef" { Token KW_typedef _ _ } -"unique" { Token KW_unique _ _ } -"wire" { Token KW_wire _ _ } +"endmodule" { Token KW_endmodule _ _ } +"enum" { Token KW_enum _ _ } +"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 _ _ } +"input" { Token KW_input _ _ } +"integer" { Token KW_integer _ _ } +"interface" { Token KW_interface _ _ } +"localparam" { Token KW_localparam _ _ } +"logic" { Token KW_logic _ _ } +"module" { Token KW_module _ _ } +"modport" { Token KW_modport _ _ } +"negedge" { Token KW_negedge _ _ } +"or" { Token KW_or _ _ } +"output" { Token KW_output _ _ } +"packed" { Token KW_packed _ _ } +"parameter" { Token KW_parameter _ _ } +"posedge" { Token KW_posedge _ _ } +"reg" { Token KW_reg _ _ } +"return" { Token KW_return _ _ } +"static" { Token KW_static _ _ } +"struct" { Token KW_struct _ _ } +"typedef" { Token KW_typedef _ _ } +"unique" { Token KW_unique _ _ } +"wire" { Token KW_wire _ _ } -simpleIdentifier { Token Id_simple _ _ } -escapedIdentifier { Token Id_escaped _ _ } -systemIdentifier { Token Id_system _ _ } -number { Token Lit_number _ _ } -string { Token Lit_string _ _ } +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 _ _ } @@ -138,8 +138,8 @@ string { Token Lit_string _ _ } "*>" { 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_eq_eq_question _ _ } +"!=?" { Token Sym_bang_eq_question _ _ } ">>>" { Token Sym_gt_gt_gt _ _ } "<<<" { Token Sym_lt_lt_lt _ _ } "<<=" { Token Sym_lt_lt_eq _ _ } @@ -154,6 +154,7 @@ string { Token Lit_string _ _ } "<<<=" { Token Sym_lt_lt_lt_eq _ _ } ">>>=" { Token Sym_gt_gt_gt_eq _ _ } +-- operator precedences, from *lowest* to *highest* %nonassoc NoElse %nonassoc "else" %right "?" ":" @@ -162,12 +163,13 @@ string { Token Lit_string _ _ } %left "|" "~|" %left "^" "^~" %left "&" "~&" -%left "==" "!=" "===" "!==" +%left "==" "!=" "===" "!==" "==?" "!=?" %left "<" "<=" ">" ">=" %left "<<" ">>" "<<<" ">>>" %left "+" "-" %left "*" "/" "%" -%left UPlus UMinus "!" "~" RedOps +%left "**" +%right UPlus UMinus "!" "~" RedOps "++" "--" %left "(" ")" "[" "]" "." @@ -280,7 +282,6 @@ DeclToken :: { DeclToken } | Identifier "." Identifier { DTType $ InterfaceT $1 (Just $3) } | "[" Expr "]" { DTBit $2 } | "{" LHSs "}" { DTConcat $2 } - -- | LHS "." Identifier { LHSDot $1 $3 } VariablePortIdentifiers :: { [(Identifier, Maybe Expr)] } : VariablePortIdentifier { [$1] } @@ -409,7 +410,7 @@ StmtNonAsgn :: { Stmt } | "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 } - | CaseKW "(" Expr ")" Cases opt(CaseDefault) "endcase" { Case $1 $3 $5 $6 } + | Unique CaseKW "(" Expr ")" Cases opt(CaseDefault) "endcase" { Case $1 $2 $4 $6 $7 } | EventControl Stmt { Timing $1 $2 } | "return" Expr ";" { Return $2 } @@ -422,12 +423,14 @@ DeclOrStmt :: { ([Decl], [Stmt]) } | "parameter" ParamType DeclAsgns ";" { (map (uncurry $ Parameter $2) $3, []) } | "localparam" ParamType DeclAsgns ";" { (map (uncurry $ Localparam $2) $3, []) } +Unique :: { Bool } + : "unique" { True } + | {- empty -} { False } + 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 } + : "case" { CaseN } + | "casex" { CaseX } + | "casez" { CaseZ } Cases :: { [Case] } : {- empty -} { [] } @@ -482,8 +485,13 @@ Expr :: { Expr } | Expr "*" Expr { BinOp Mul $1 $3 } | Expr "/" Expr { BinOp Div $1 $3 } | Expr "%" Expr { BinOp Mod $1 $3 } +| Expr "**" Expr { BinOp Pow $1 $3 } | Expr "<<<" Expr { BinOp ShiftAL $1 $3 } | Expr ">>>" Expr { BinOp ShiftAR $1 $3 } +| Expr "===" Expr { BinOp TEq $1 $3 } +| Expr "!==" Expr { BinOp TNe $1 $3 } +| Expr "==?" Expr { BinOp WEq $1 $3 } +| Expr "!=?" Expr { BinOp WNe $1 $3 } | "!" Expr { UniOp Not $2 } | "~" Expr { UniOp BWNot $2 } | "+" Expr %prec UPlus { UniOp UAdd $2 } @@ -525,7 +533,7 @@ GenItem :: { GenItem } | "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 } + | "for" "(" Identifier "=" Expr ";" Expr ";" GenvarIteration ")" "begin" ":" Identifier GenItems "end" { GenFor ($3, $5) $7 $9 $13 $14 } -- TODO: We should restrict it to the module items that are actually allowed. | ModuleItem { genItemsToGenItem $ map GenModuleItem $1 } @@ -539,6 +547,29 @@ GenCase :: { GenCase } GenCaseDefault :: { GenItem } : "default" opt(":") GenItemOrNull { $3 } +GenvarIteration :: { (Identifier, AsgnOp, Expr) } + : Identifier AssignmentOperator Expr { ($1, $2, $3) } + | IncOrDecOperator Identifier { ($2, AsgnOp $1, Number "1") } + | Identifier IncOrDecOperator { ($1, AsgnOp $2, Number "1") } + +AssignmentOperator :: { AsgnOp } + : "=" { AsgnOpEq } + | "+=" { AsgnOp Add } + | "-=" { AsgnOp Sub } + | "*=" { AsgnOp Mul } + | "/=" { AsgnOp Div } + | "%=" { AsgnOp Mod } + | "&=" { AsgnOp BWAnd } + | "|=" { AsgnOp BWOr } + | "^=" { AsgnOp BWXor } + | "<<=" { AsgnOp ShiftL } + | ">>=" { AsgnOp ShiftR } + | "<<<=" { AsgnOp ShiftAL } + | ">>>=" { AsgnOp ShiftAR } + +IncOrDecOperator :: { BinOp } + : "++" { Add } + | "--" { Sub } { diff --git a/src/Language/SystemVerilog/Parser/Tokens.hs b/src/Language/SystemVerilog/Parser/Tokens.hs index 1efc98c..478418e 100644 --- a/src/Language/SystemVerilog/Parser/Tokens.hs +++ b/src/Language/SystemVerilog/Parser/Tokens.hs @@ -318,8 +318,8 @@ data TokenName | Sym_aster_gt | Sym_eq_eq_eq | Sym_bang_eq_eq - | Sym_eq_question_eq - | Sym_bang_question_eq + | Sym_eq_eq_question + | Sym_bang_eq_question | Sym_gt_gt_gt | Sym_lt_lt_lt | Sym_lt_lt_eq diff --git a/sv2v.cabal b/sv2v.cabal index 2f08bfb..abde0d4 100644 --- a/sv2v.cabal +++ b/sv2v.cabal @@ -49,6 +49,7 @@ executable sv2v Convert.StarPort Convert.Typedef Convert.Traverse + Convert.Unique -- sv2v CLI modules Job ghc-options: