{- sv2v - Author: Zachary Snow - Initial Verilog AST Author: Tom Hawkins - - SystemVerilog procedural statements -} module Language.SystemVerilog.AST.Stmt ( Stmt (..) , Timing (..) , Event (..) , EventExpr (..) , Edge (..) , CaseKW (..) , Case , ActionBlock (..) , PropExpr (..) , SeqMatchItem (..) , SeqExpr (..) , AssertionItem , Assertion (..) , AssertionKind(..) , Deferral (..) , PropertySpec (..) , ViolationCheck (..) , BlockKW (..) ) where import Text.Printf (printf) import Language.SystemVerilog.AST.ShowHelp (commas, indent, unlines', showPad, showBlock) import Language.SystemVerilog.AST.Attr (Attr) import Language.SystemVerilog.AST.Decl (Decl) import Language.SystemVerilog.AST.Expr (Expr(Call, Ident, Nil), Args(..), Range, showRange, showAssignment) import Language.SystemVerilog.AST.LHS (LHS) import Language.SystemVerilog.AST.Op (AsgnOp(AsgnOpEq)) import Language.SystemVerilog.AST.Type (Identifier) data Stmt = StmtAttr Attr Stmt | Block BlockKW Identifier [Decl] [Stmt] | Case ViolationCheck CaseKW Expr [Case] | For [(LHS, Expr)] Expr [(LHS, AsgnOp, Expr)] Stmt | Asgn AsgnOp (Maybe Timing) LHS Expr | While Expr Stmt | RepeatL Expr Stmt | DoWhile Expr Stmt | Forever Stmt | Foreach Identifier [Identifier] Stmt | If ViolationCheck Expr Stmt Stmt | Timing Timing Stmt | Return Expr | Subroutine Expr Args | Trigger Bool Identifier | Assertion Assertion | Force Bool LHS Expr | Continue | Break | Null | CommentStmt String deriving Eq instance Show Stmt where showList l _ = unlines' $ map show l show (StmtAttr attr stmt) = printf "%s\n%s" (show attr) (show stmt) show (Block kw name decls stmts) = printf "%s%s\n%s\n%s" (show kw) header body (blockEndToken kw) where header = if null name then "" else " : " ++ name body = showBlock decls stmts show (Case u kw e cs) = printf "%s%s (%s)%s\n%s\nendcase" (showPad u) (show kw) (show e) insideStr bodyStr where insideStr = if kw == CaseInside then " inside" else "" bodyStr = indent $ unlines' $ map showCase cs show (For inits cond assigns stmt) = printf "for (%s; %s; %s)\n%s" (showInits inits) (show cond) (commas $ map showAssign assigns) (indent $ show stmt) where showInits :: [(LHS, Expr)] -> String showInits = commas . map showInit where showInit (l, e) = showAssign (l, AsgnOpEq, e) show (Subroutine e a) = printf "%s%s;" (show e) aStr where aStr = if a == Args [] [] then "" else show a show (Asgn o t v e) = printf "%s %s %s%s;" (show v) (show o) tStr (show e) where tStr = maybe "" showPad t show (If u c s Null) = printf "%sif (%s)%s" (showPad u) (show c) (showBranch s) show (If u c s1 s2 ) = printf "%sif (%s)%s\nelse%s" (showPad u) (show c) (showBlockedBranch s1) (showElseBranch s2) show (While e s) = printf "while (%s) %s" (show e) (show s) show (RepeatL e s) = printf "repeat (%s) %s" (show e) (show s) show (DoWhile e s) = printf "do %s while (%s);" (show s) (show e) show (Forever s) = printf "forever %s" (show s) show (Foreach x i s) = printf "foreach (%s [ %s ]) %s" x (commas i) (show s) show (Return e ) = printf "return %s;" (show e) show (Timing t s) = printf "%s%s" (show t) (showShortBranch s) show (Trigger b x) = printf "->%s %s;" (if b then "" else ">") x show (Assertion a) = show a show (Force kw l e) = printf "%s %s%s;" kwStr (show l) (showAssignment e) where kwStr = case (kw, e /= Nil) of (True , True ) -> "force" (True , False) -> "release" (False, True ) -> "assign" (False, False) -> "deassign" show (Continue ) = "continue;" show (Break ) = "break;" show (Null ) = ";" show (CommentStmt c) = "// " ++ c showAssign :: (LHS, AsgnOp, Expr) -> String showAssign (l, op, e) = (showPad l) ++ (showPad op) ++ (show e) showBranch :: Stmt -> String showBranch (Block Seq "" [] stmts@[CommentStmt{}, _]) = '\n' : (indent $ show stmts) showBranch block@Block{} = ' ' : show block showBranch stmt = '\n' : (indent $ show stmt) showBlockedBranch :: Stmt -> String showBlockedBranch stmt = showBranch $ if isControl stmt then Block Seq "" [] [stmt] else stmt where isControl s = case s of If{} -> True For{} -> True While{} -> True RepeatL{} -> True DoWhile{} -> True Forever{} -> True Foreach{} -> True Timing _ subStmt -> isControl subStmt Block Seq "" [] [CommentStmt{}, subStmt] -> isControl subStmt _ -> False showElseBranch :: Stmt -> String showElseBranch stmt@If{} = ' ' : show stmt showElseBranch stmt = showBranch stmt showShortBranch :: Stmt -> String showShortBranch stmt@Asgn{} = ' ' : show stmt showShortBranch stmt = showBranch stmt showCase :: Case -> String showCase (a, b) = printf "%s:%s" exprStr (showShortBranch b) where exprStr = case a of [] -> "default" _ -> commas $ map show a data CaseKW = CaseN | CaseZ | CaseX | CaseInside deriving Eq instance Show CaseKW where show CaseN = "case" show CaseZ = "casez" show CaseX = "casex" show CaseInside = "case" type Case = ([Expr], Stmt) data Timing = Event Event | Delay Expr | Cycle Expr deriving Eq instance Show Timing where show (Event e) = printf "@(%s)" (show e) show (Delay e) = printf "#(%s)" (show e) show (Cycle e) = printf "##(%s)" (show e) data Event = EventStar | EventExpr EventExpr deriving Eq instance Show Event where show EventStar = "*" show (EventExpr e) = show e data EventExpr = EventExprEdge Edge Expr | EventExprOr EventExpr EventExpr deriving Eq instance Show EventExpr where show (EventExprEdge g e) = printf "%s%s" (showPad g) (show e) show (EventExprOr a b) = printf "%s or %s" (show a) (show b) data Edge = Posedge | Negedge | Edge | NoEdge deriving Eq instance Show Edge where show Posedge = "posedge" show Negedge = "negedge" show Edge = "edge" show NoEdge = "" data ActionBlock = ActionBlock Stmt Stmt deriving Eq instance Show ActionBlock where show (ActionBlock s Null) = printf " %s" (show s) show (ActionBlock Null s) = printf " else %s" (show s) show (ActionBlock s1 s2) = printf " %s else %s" (show s1) (show s2) data PropExpr = PropExpr SeqExpr | PropExprImpliesO SeqExpr PropExpr | PropExprImpliesNO SeqExpr PropExpr | PropExprFollowsO SeqExpr PropExpr | PropExprFollowsNO SeqExpr PropExpr | PropExprIff PropExpr PropExpr deriving Eq instance Show PropExpr where show (PropExpr se) = show se show (PropExprImpliesO a b) = printf "(%s |-> %s)" (show a) (show b) show (PropExprImpliesNO a b) = printf "(%s |=> %s)" (show a) (show b) show (PropExprFollowsO a b) = printf "(%s #-# %s)" (show a) (show b) show (PropExprFollowsNO a b) = printf "(%s #=# %s)" (show a) (show b) show (PropExprIff a b) = printf "(%s iff %s)" (show a) (show b) data SeqMatchItem = SeqMatchAsgn (LHS, AsgnOp, Expr) | SeqMatchCall Identifier Args deriving Eq instance Show SeqMatchItem where show (SeqMatchAsgn asgn) = showAssign asgn show (SeqMatchCall ident args) = show $ Call (Ident ident) args data SeqExpr = SeqExpr Expr | SeqExprAnd SeqExpr SeqExpr | SeqExprOr SeqExpr SeqExpr | SeqExprIntersect SeqExpr SeqExpr | SeqExprThroughout Expr SeqExpr | SeqExprWithin SeqExpr SeqExpr | SeqExprDelay (Maybe SeqExpr) Range SeqExpr | SeqExprFirstMatch SeqExpr [SeqMatchItem] deriving Eq instance Show SeqExpr where show (SeqExpr a ) = show a show (SeqExprAnd a b) = printf "(%s %s %s)" (show a) "and" (show b) show (SeqExprOr a b) = printf "(%s %s %s)" (show a) "or" (show b) show (SeqExprIntersect a b) = printf "(%s %s %s)" (show a) "intersect" (show b) show (SeqExprThroughout a b) = printf "(%s %s %s)" (show a) "throughout" (show b) show (SeqExprWithin a b) = printf "(%s %s %s)" (show a) "within" (show b) show (SeqExprDelay me r s) = printf "%s##%s %s" (maybe "" showPad me) (showCycleDelayRange r) (show s) show (SeqExprFirstMatch e a) = printf "first_match(%s, %s)" (show e) (commas $ map show a) showCycleDelayRange :: Range -> String showCycleDelayRange (Nil, e) = printf "(%s)" (show e) showCycleDelayRange (e, Nil) = printf "[%s:$]" (show e) showCycleDelayRange r = showRange r type AssertionItem = (Identifier, Assertion) data Assertion = Assert AssertionKind ActionBlock | Assume AssertionKind ActionBlock | Cover AssertionKind Stmt deriving Eq instance Show Assertion where show (Assert k a) = printf "assert %s%s" (show k) (show a) show (Assume k a) = printf "assume %s%s" (show k) (show a) show (Cover k a) = printf "cover %s%s" (show k) (show a) data AssertionKind = Concurrent PropertySpec | Immediate Deferral Expr deriving Eq instance Show AssertionKind where show (Concurrent e) = printf "property (%s\n)" (show e) show (Immediate d e) = printf "%s(%s)" (showPad d) (show e) data Deferral = NotDeferred | ObservedDeferred | FinalDeferred deriving Eq instance Show Deferral where show NotDeferred = "" show ObservedDeferred = "#0" show FinalDeferred = "final" data PropertySpec = PropertySpec (Maybe EventExpr) Expr PropExpr deriving Eq instance Show PropertySpec where show (PropertySpec mv e pe) = printf "%s%s\n\t%s" mvStr eStr (show pe) where mvStr = case mv of Nothing -> "" Just v -> printf "@(%s) " (show v) eStr = case e of Nil -> "" _ -> printf "disable iff (%s)" (show e) data ViolationCheck = Unique | Unique0 | Priority | NoCheck deriving Eq instance Show ViolationCheck where show Unique = "unique" show Unique0 = "unique0" show Priority = "priority" show NoCheck = "" data BlockKW = Seq | Par deriving Eq instance Show BlockKW where show Seq = "begin" show Par = "fork" blockEndToken :: BlockKW -> Identifier blockEndToken Seq = "end" blockEndToken Par = "join"