From 5b035613ee8e95e318f4747ac415587c7c26d9ac Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Tue, 8 Aug 2023 22:25:39 -0400 Subject: [PATCH] constant fold || and && --- CHANGELOG.md | 4 ++++ src/Convert/ExprUtils.hs | 22 +++++++++++++++++++++ test/basic/simplify_binop.sv | 33 +++++++++++++++++++++++++++++++- test/basic/simplify_binop.sv.pat | 2 ++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 test/basic/simplify_binop.sv.pat diff --git a/CHANGELOG.md b/CHANGELOG.md index 878577a..8ea7d50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ * Fixed certain non-ANSI style port declarations being incorrectly reported as incompatible +### Other Enhancements + +* Added constant folding for `||` and `&&` + ## v0.0.11 ### New Features diff --git a/src/Convert/ExprUtils.hs b/src/Convert/ExprUtils.hs index 63cd783..2fcb37f 100644 --- a/src/Convert/ExprUtils.hs +++ b/src/Convert/ExprUtils.hs @@ -161,6 +161,9 @@ simplifyBinOp op (Number n) (ConvertedUU sz v k) | isCmpOp op = simplifyBinOp op (ConvertedUU sz v k) (Number n) | isCmpOp op = simplifyBinOp op (uuExtend sz v k) (Number n) +simplifyBinOp op (Number n) e | op == LogAnd || op == LogOr = + simplifyLogAndOr op n e + simplifyBinOp op e1 e2 = case (e1, e2) of (Dec x, Dec y) -> constantFold orig op x y @@ -327,3 +330,22 @@ simplifyRange (e1, e2) = (simplify e1, simplify e2) simplifyDimensions :: [Range] -> [Range] simplifyDimensions = map simplifyRange + +-- TODO: extend this to other logical binary operators +simplifyLogAndOr :: BinOp -> Number -> Expr -> Expr +simplifyLogAndOr op n1 (Number n2) = + case (numberToInteger n1, numberToInteger n2) of + (Just v, _) | (v /= 0) == isOr -> bool isOr + (_, Just v) | (v /= 0) == isOr -> bool isOr + (Nothing, _) -> boolUnknown + (_, Nothing) -> boolUnknown + _ -> bool $ not isOr + where + isOr = op == LogOr + boolUnknown = Number $ Based 1 False Binary 0 1 +simplifyLogAndOr op n e = + case numberToInteger n of + Just v | (v /= 0) == isOr -> bool isOr + Just _ -> UniOp LogNot $ UniOp LogNot e + Nothing -> BinOp op (Number n) e + where isOr = op == LogOr diff --git a/test/basic/simplify_binop.sv b/test/basic/simplify_binop.sv index 665fa5a..fd66091 100644 --- a/test/basic/simplify_binop.sv +++ b/test/basic/simplify_binop.sv @@ -1,3 +1,34 @@ +`define TEST(expr) initial begin : \blk``expr \ + localparam X = expr; \ + localparam [63:0] Y = X; \ + $display(`"expr %b %b %b`", expr, X, Y); \ +end + +`define TEST_LOGOP(op) \ + `TEST(0``op``0) \ + `TEST(0``op``1) \ + `TEST(0``op``1'bx) \ + `TEST(0``op``P) \ + `TEST(0``op``Q) \ + `TEST(0``op``R) \ + `TEST(1``op``0) \ + `TEST(1``op``1) \ + `TEST(1``op``1'bx) \ + `TEST(1``op``P) \ + `TEST(1``op``Q) \ + `TEST(1``op``R) \ + `TEST(1'bx``op``0) \ + `TEST(1'bx``op``1) \ + `TEST(1'bx``op``1'bx) \ + `TEST(1'bx``op``P) \ + `TEST(1'bx``op``Q) \ + `TEST(1'bx``op``R) + module top; - initial $display("%b", (12'hb03 - 12'hb07) + 12'hb10); + `TEST((12'hb03-12'hb07)+12'hb10) + parameter P = 0; + parameter Q = 1; + parameter R = 1'bx; + `TEST_LOGOP(||) + `TEST_LOGOP(&&) endmodule diff --git a/test/basic/simplify_binop.sv.pat b/test/basic/simplify_binop.sv.pat new file mode 100644 index 0000000..e39ce50 --- /dev/null +++ b/test/basic/simplify_binop.sv.pat @@ -0,0 +1,2 @@ +reject || 1 +reject && 1