From de728f30601ebb1512ab54e28867509fd8f59822 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 4 Mar 2019 20:58:09 -0500 Subject: [PATCH] added some support for a few key non-synthesizable constructs --- src/Convert/AlwaysKW.hs | 2 +- src/Convert/Traverse.hs | 11 ++- src/Language/SystemVerilog/AST.hs | 26 ++++-- src/Language/SystemVerilog/Parser/Parse.y | 86 +++++++++++-------- .../SystemVerilog/Parser/ParseDecl.hs | 4 +- 5 files changed, 85 insertions(+), 44 deletions(-) diff --git a/src/Convert/AlwaysKW.hs b/src/Convert/AlwaysKW.hs index 8ad2a58..ae5c782 100644 --- a/src/Convert/AlwaysKW.hs +++ b/src/Convert/AlwaysKW.hs @@ -18,7 +18,7 @@ convert = traverseDescriptions $ traverseModuleItems replaceAlwaysKW replaceAlwaysKW :: ModuleItem -> ModuleItem replaceAlwaysKW (AlwaysC AlwaysComb stmt) = - AlwaysC Always $ Timing SenseStar stmt + AlwaysC Always $ Timing (Event SenseStar) stmt replaceAlwaysKW (AlwaysC AlwaysFF stmt) = AlwaysC Always stmt replaceAlwaysKW other = other diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index b9e4669..794b6b4 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -97,6 +97,8 @@ traverseStmtsM mapper = moduleItemMapper moduleItemMapper (Function lifetime ret name decls stmts) = do stmts' <- mapM fullMapper stmts return $ Function lifetime ret name decls stmts' + moduleItemMapper (Initial stmt) = + fullMapper stmt >>= return . Initial moduleItemMapper other = return $ other fullMapper = traverseNestedStmtsM mapper @@ -125,8 +127,9 @@ traverseNestedStmtsM mapper = fullMapper s1' <- fullMapper s1 s2' <- fullMapper s2 return $ If e s1' s2' - cs (Timing sense stmt) = fullMapper stmt >>= return . Timing sense + cs (Timing event stmt) = fullMapper stmt >>= return . Timing event cs (Return expr) = return $ Return expr + cs (Subroutine f exprs) = return $ Subroutine f exprs cs (Null) = return Null traverseStmtLHSsM :: Monad m => MapperM m LHS -> MapperM m Stmt @@ -238,7 +241,9 @@ traverseExprsM mapper = moduleItemMapper return $ For (x1, e1') cc' (x2, e2') stmt flatStmtMapper (If cc s1 s2) = exprMapper cc >>= \cc' -> return $ If cc' s1 s2 - flatStmtMapper (Timing sense stmt) = return $ Timing sense stmt + flatStmtMapper (Timing event stmt) = return $ Timing event stmt + flatStmtMapper (Subroutine f exprs) = + mapM exprMapper exprs >>= return . Subroutine f flatStmtMapper (Return expr) = exprMapper expr >>= return . Return flatStmtMapper (Null) = return Null @@ -252,6 +257,8 @@ traverseExprsM mapper = moduleItemMapper exprMapper expr >>= return . Assign lhs moduleItemMapper (AlwaysC kw stmt) = stmtMapper stmt >>= return . AlwaysC kw + moduleItemMapper (Initial stmt) = + stmtMapper stmt >>= return . Initial moduleItemMapper (Function lifetime ret f decls stmts) = do decls' <- mapM declMapper decls stmts' <- mapM stmtMapper stmts diff --git a/src/Language/SystemVerilog/AST.hs b/src/Language/SystemVerilog/AST.hs index b593f20..31b4bd4 100644 --- a/src/Language/SystemVerilog/AST.hs +++ b/src/Language/SystemVerilog/AST.hs @@ -12,6 +12,7 @@ module Language.SystemVerilog.AST , BinOp (..) , AsgnOp (..) , Sense (..) + , Timing (..) , GenItem (..) , AlwaysKW (..) , CaseKW (..) @@ -156,11 +157,9 @@ data ModuleItem | Genvar Identifier | Generate [GenItem] | Modport Identifier [ModportDecl] + | Initial Stmt deriving Eq --- "function inputs and outputs are inferred to be of type reg if no internal --- data types for the ports are declared" - data AlwaysKW = Always | AlwaysComb @@ -189,7 +188,8 @@ instance Show ModuleItem where Function ml t x i b -> printf "function %s%s%s;\n%s\n%s\nendfunction" (showLifetime ml) (showPad t) x (indent $ show i) (indent $ unlines' $ map show b) Genvar x -> printf "genvar %s;" x Generate b -> printf "generate\n%s\nendgenerate" (indent $ unlines' $ map show b) - Modport x l -> printf "modport %s(\n%s\n);" x (indent $ intercalate ",\n" $ map showModportDecl l) + Modport x l -> printf "modport %s(\n%s\n);" x (indent $ intercalate ",\n" $ map showModportDecl l) + Initial s -> printf "initial %s" (show s) where showMaybePorts = maybe "(.*)" showPorts showPorts :: [PortBinding] -> String @@ -401,8 +401,9 @@ data Stmt | AsgnBlk LHS Expr | Asgn LHS Expr | If Expr Stmt Stmt - | Timing Sense Stmt + | Timing Timing Stmt | Return Expr + | Subroutine Identifier [Expr] | Null deriving Eq @@ -431,9 +432,11 @@ instance Show Stmt where show (If a b Null) = printf "if (%s) %s" (show a) (show b) show (If a b c ) = printf "if (%s) %s\nelse %s" (show a) (show b) (show c) show (Return e ) = printf "return %s;" (show e) - show (Timing t s ) = printf "@(%s)%s" (show t) rest + show (Subroutine x a) = printf "%s(%s);" x (commas $ map show a) + show (Timing t s ) = printf "%s%s" (show t) rest where rest = case s of + Null -> ";" Block _ _ -> " " ++ (show s) _ -> "\n" ++ (indent $ show s) show (Null ) = ";" @@ -443,6 +446,17 @@ type Case = ([Expr], Stmt) showCase :: (Show x, Show y) => ([x], y) -> String showCase (a, b) = printf "%s: %s" (commas $ map show a) (show b) +data Timing + = Event Sense + | Delay Expr + | Cycle Expr + deriving Eq + +instance Show Timing where + show (Event s) = printf "@(%s)" (show s) + show (Delay e) = printf "#(%s)" (show e) + show (Cycle e) = printf "##(%s)" (show e) + data Sense = Sense LHS | SenseOr Sense Sense diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index efe2afa..66c4a72 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -265,23 +265,31 @@ Identifiers :: { [Identifier] } -- uses delimiter propagation hack to avoid conflicts DeclTokens(delim) :: { [DeclToken] } - : DeclToken delim { [$1] } - | DeclToken DeclTokens(delim) { [$1] ++ $2 } - | "=" Expr "," DeclTokens(delim) { [DTAsgn $2, DTComma] ++ $4 } - | "<=" Expr "," DeclTokens(delim) { [DTAsgnNBlk $2, DTComma] ++ $4 } - | "=" Expr delim { [DTAsgn $2] } - | "<=" Expr delim { [DTAsgnNBlk $2] } + : DeclToken delim { [$1] } + | DeclToken DeclTokens(delim) { [$1] ++ $2 } + | "=" Expr "," DeclTokens(delim) { [DTAsgn $2, DTComma] ++ $4 } + | "=" Expr delim { [DTAsgn $2] } DeclToken :: { DeclToken } + : DeclOrStmtToken { $1 } + | ParameterBindings { DTParams $1 } + | ModuleInstantiation { DTInstance $1 } + +DeclOrStmtTokens(delim) :: { [DeclToken] } + : DeclOrStmtToken delim { [$1] } + | DeclOrStmtToken DeclOrStmtTokens(delim) { [$1] ++ $2 } + | "=" Expr "," DeclOrStmtTokens(delim) { [DTAsgn $2, DTComma] ++ $4 } + | "<=" Expr "," DeclOrStmtTokens(delim) { [DTAsgnNBlk $2, DTComma] ++ $4 } + | "=" Expr delim { [DTAsgn $2] } + | "<=" Expr delim { [DTAsgnNBlk $2] } +DeclOrStmtToken :: { DeclToken } : "," { DTComma } - | Range { DTRange $1 } - | Identifier { DTIdent $1 } - | Direction { DTDir $1 } - | ParameterBindings { DTParams $1 } - | ModuleInstantiation { DTInstance $1 } - | PartialType { DTType $1 } + | Range { DTRange $1 } + | Identifier { DTIdent $1 } + | Direction { DTDir $1 } + | "[" Expr "]" { DTBit $2 } + | "{" LHSs "}" { DTConcat $2 } + | PartialType { DTType $1 } | Identifier "." Identifier { DTType $ InterfaceT $1 (Just $3) } - | "[" Expr "]" { DTBit $2 } - | "{" LHSs "}" { DTConcat $2 } VariablePortIdentifiers :: { [(Identifier, Maybe Expr)] } : VariablePortIdentifier { [$1] } @@ -306,6 +314,7 @@ ModuleItem :: { [ModuleItem] } | "localparam" ParamType DeclAsgns ";" { map MIDecl $ map (uncurry $ Localparam $2) $3 } | "assign" LHS "=" Expr ";" { [Assign $2 $4] } | AlwaysKW Stmt { [AlwaysC $1 $2] } + | "initial" Stmt { [Initial $2] } | "genvar" Identifiers ";" { map Genvar $2 } | "generate" GenItems "endgenerate" { [Generate $2] } | "modport" ModportItems ";" { map (uncurry Modport) $2 } @@ -338,13 +347,6 @@ ParamType :: { Type } : Dimensions { Implicit $1 } | "integer" { IntegerT } -EventControl :: { Sense } - : "@" "(" Sense ")" { $3 } - | "@" "(" "*" ")" { SenseStar } - | "@" "(*)" { SenseStar } - | "@" "*" { SenseStar } - | "@*" { SenseStar } - Dimensions :: { [Range] } : {- empty -} { [] } | DimensionsNonEmpty { $1 } @@ -372,15 +374,6 @@ LHSs :: { [LHS] } : LHS { [$1] } | 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)] } : {- empty -} { [] } | BindingsNonEmpty { $1 } @@ -403,6 +396,7 @@ Stmt :: { Stmt } : StmtNonAsgn { $1 } | LHS "=" Expr ";" { AsgnBlk $1 $3 } | LHS "<=" Expr ";" { Asgn $1 $3 } + | Identifier ";" { Subroutine $1 [] } StmtNonAsgn :: { Stmt } : ";" { Null } | "begin" Stmts "end" { Block Nothing $2 } @@ -411,18 +405,39 @@ StmtNonAsgn :: { Stmt } | "if" "(" Expr ")" Stmt %prec NoElse { If $3 $5 Null } | "for" "(" Identifier "=" Expr ";" Expr ";" Identifier "=" Expr ")" Stmt { For ($3, $5) $7 ($9, $11) $13 } | Unique CaseKW "(" Expr ")" Cases opt(CaseDefault) "endcase" { Case $1 $2 $4 $6 $7 } - | EventControl Stmt { Timing $1 $2 } + | TimingControl Stmt { Timing $1 $2 } | "return" Expr ";" { Return $2 } + | Identifier "(" CallArgs ")" ";" { Subroutine $1 $3 } DeclsAndStmts :: { ([Decl], [Stmt]) } : DeclOrStmt DeclsAndStmts { combineDeclsAndStmts $1 $2 } | StmtNonAsgn Stmts { ([], $1 : $2) } | {- empty -} { ([], []) } DeclOrStmt :: { ([Decl], [Stmt]) } - : DeclTokens(";") { parseDTsAsDeclOrAsgn $1 } + : DeclOrStmtTokens(";") { parseDTsAsDeclOrAsgn $1 } | "parameter" ParamType DeclAsgns ";" { (map (uncurry $ Parameter $2) $3, []) } | "localparam" ParamType DeclAsgns ";" { (map (uncurry $ Localparam $2) $3, []) } +TimingControl :: { Timing } + : DelayControl { $1 } + | CycleDelay { $1 } + | EventControl { $1 } +DelayControl :: { Timing } + : "#" Expr { Delay $2 } +CycleDelay :: { Timing } + : "##" Expr { Cycle $2 } +EventControl :: { Timing } + : "@" "(" Senses ")" { Event $3 } + | "@" "(*)" { Event SenseStar } + | "@*" { Event SenseStar } +Senses :: { Sense } + : Sense { $1 } + | Senses "or" Sense { SenseOr $1 $3 } +Sense :: { Sense } + : LHS { Sense $1 } + | "posedge" LHS { SensePosedge $2 } + | "negedge" LHS { SenseNegedge $2 } + Unique :: { Bool } : "unique" { True } | {- empty -} { False } @@ -449,8 +464,11 @@ String :: { String } : string { tail $ init $ tokenString $1 } CallArgs :: { [Expr] } - : Expr { [$1] } - | CallArgs "," Expr { $1 ++ [$3] } + : {- empty -} { [] } + | CallArgsNonEmpty { $1 } +CallArgsNonEmpty :: { [Expr] } + : Expr { [$1] } + | CallArgsNonEmpty "," Expr { $1 ++ [$3] } Exprs :: { [Expr] } : Expr { [$1] } diff --git a/src/Language/SystemVerilog/Parser/ParseDecl.hs b/src/Language/SystemVerilog/Parser/ParseDecl.hs index 9a881f4..2939e0d 100644 --- a/src/Language/SystemVerilog/Parser/ParseDecl.hs +++ b/src/Language/SystemVerilog/Parser/ParseDecl.hs @@ -140,8 +140,10 @@ parseDTsAsDecl tokens = where components = parseDTsAsComponents tokens --- [PUBLIC]: parser for single block item declarations of assign statetments +-- [PUBLIC]: parser for single block item declarations or assign or arg-less +-- subroutine call statetments parseDTsAsDeclOrAsgn :: [DeclToken] -> ([Decl], [Stmt]) +parseDTsAsDeclOrAsgn [DTIdent f] = ([], [Subroutine f []]) parseDTsAsDeclOrAsgn tokens = if any isAsgnToken tokens || tripLookahead tokens then ([], [constructor lhs expr])