From effeded6d17ff2efae22f5a65b9963cf55ca8b3d Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Tue, 10 May 2022 12:11:32 -0400 Subject: [PATCH] support procedural continuous assignments --- CHANGELOG.md | 2 ++ src/Convert/Traverse.hs | 10 ++++++++++ src/Language/SystemVerilog/AST/Stmt.hs | 10 +++++++++- src/Language/SystemVerilog/Parser/Parse.y | 4 ++++ test/basic/force.sv | 19 +++++++++++++++++++ 5 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 test/basic/force.sv diff --git a/CHANGELOG.md b/CHANGELOG.md index b3df42a..04919ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ * Added support for complex event expressions (e.g., `@(x ^ y)`) * Added support for the SystemVerilog `edge` event * Added support for cycle delay ranges in assertion sequence expressions +* Added support for procedural continuous assignments (`assign`/`deassign` and + `force`/`release`) * Added conversion for `do` `while` loops * Added support for passing through DPI imports and exports * Added support for passing through functions with output ports diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index 68cac0f..247dea5 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -255,6 +255,7 @@ traverseSinglyNestedStmtsM fullMapper = cs cs (Return expr) = return $ Return expr cs (Subroutine expr exprs) = return $ Subroutine expr exprs cs (Trigger blocks x) = return $ Trigger blocks x + cs stmt@Force{} = return stmt cs (Assertion a) = traverseAssertionStmtsM fullMapper a >>= return . Assertion cs (Continue) = return Continue @@ -374,6 +375,8 @@ traverseStmtLHSsM mapper = stmtMapper lhss' <- mapM fullMapper lhss let incrs' = zip3 lhss' asgnOps exprs return $ For inits' me incrs' stmt + stmtMapper (Force kw l e) = + fullMapper l >>= \l' -> return $ Force kw l' e stmtMapper other = return other traverseStmtLHSs :: Mapper LHS -> Mapper Stmt @@ -682,6 +685,10 @@ traverseStmtExprsM exprMapper = flatStmtMapper flatStmtMapper (Return expr) = exprMapper expr >>= return . Return flatStmtMapper (Trigger blocks x) = return $ Trigger blocks x + flatStmtMapper (Force kw l e) = do + l' <- lhsMapper l + e' <- exprMapper e + return $ Force kw l' e' flatStmtMapper (Assertion a) = traverseAssertionExprsM exprMapper a >>= return . Assertion flatStmtMapper (Continue) = return Continue @@ -1075,6 +1082,9 @@ traverseStmtAsgnsM mapper = stmtMapper stmtMapper (Asgn op mt lhs expr) = do (lhs', expr') <- mapper (lhs, expr) return $ Asgn op mt lhs' expr' + stmtMapper (Force kw lhs expr) | expr /= Nil = do + (lhs', expr') <- mapper (lhs, expr) + return $ Force kw lhs' expr' stmtMapper other = return other traverseStmtAsgns :: Mapper (LHS, Expr) -> Mapper Stmt diff --git a/src/Language/SystemVerilog/AST/Stmt.hs b/src/Language/SystemVerilog/AST/Stmt.hs index be4e273..00b6d4c 100644 --- a/src/Language/SystemVerilog/AST/Stmt.hs +++ b/src/Language/SystemVerilog/AST/Stmt.hs @@ -31,7 +31,7 @@ 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) +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) @@ -53,6 +53,7 @@ data Stmt | Subroutine Expr Args | Trigger Bool Identifier | Assertion Assertion + | Force Bool LHS Expr | Continue | Break | Null @@ -98,6 +99,13 @@ instance Show Stmt where 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 ) = ";" diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index c2dbc06..bf4c9b2 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -1134,6 +1134,10 @@ StmtNonBlock :: { Stmt } | AttributeInstance Stmt { StmtAttr $1 $2 } | ProceduralAssertionStatement { Assertion $1 } | "void" "'" "(" Expr CallArgs ")" ";" { Subroutine $4 $5 } + | "assign" LHS "=" Expr ";" { Force False $2 $4 } + | "deassign" LHS ";" { Force False $2 Nil } + | "force" LHS "=" Expr ";" { Force True $2 $4 } + | "release" LHS ";" { Force True $2 Nil } OptDelayOrEvent :: { Maybe Timing } : DelayOrEvent { Just $1 } diff --git a/test/basic/force.sv b/test/basic/force.sv new file mode 100644 index 0000000..16d7be7 --- /dev/null +++ b/test/basic/force.sv @@ -0,0 +1,19 @@ +module top; + reg [1:0] a, b; + wire [1:0] c, d; + initial begin + $monitor("%2d %b %b %b %b", $time, a, b, c, d); + #1 force c = 1; + #1 release c; + #1 force c = b; + #1 force d = a; + #1 release c; + #1 assign a = 1; + #1 assign a = 3; + #1 assign b = 2; + #1 a = 0; + #1 deassign a; + #1 a = 0; + #1 release d; + end +endmodule