From 851a1de1729d689d6d74c303d685fb7cf1f28466 Mon Sep 17 00:00:00 2001 From: Anqi Yu Date: Thu, 23 May 2024 14:32:47 +0800 Subject: [PATCH] [ImportVerilog] Support set membership operator. (#7066) --- lib/Conversion/ImportVerilog/Expressions.cpp | 69 ++++++++++++++++++++ test/Conversion/ImportVerilog/basic.sv | 26 ++++++++ test/Conversion/ImportVerilog/errors.sv | 19 ++++++ 3 files changed, 114 insertions(+) diff --git a/lib/Conversion/ImportVerilog/Expressions.cpp b/lib/Conversion/ImportVerilog/Expressions.cpp index 34104fb5169d..c387841279a8 100644 --- a/lib/Conversion/ImportVerilog/Expressions.cpp +++ b/lib/Conversion/ImportVerilog/Expressions.cpp @@ -435,6 +435,75 @@ struct ExprVisitor { context.convertExpression(expr.value())); } + // Handle set membership operator. + Value visit(const slang::ast::InsideExpression &expr) { + auto lhs = convertToSimpleBitVector(context.convertExpression(expr.left())); + if (!lhs) + return {}; + // All conditions for determining whether it is inside. + SmallVector conditions; + + // Traverse open range list. + for (const auto *listExpr : expr.rangeList()) { + Value cond; + // The open range list on the right-hand side of the inside operator is a + // comma-separated list of expressions or ranges. + if (const auto *openRange = + listExpr->as_if()) { + // Handle ranges. + auto lowBound = convertToSimpleBitVector( + context.convertExpression(openRange->left())); + auto highBound = convertToSimpleBitVector( + context.convertExpression(openRange->right())); + if (!lowBound || !highBound) + return {}; + Value leftValue, rightValue; + // Determine if the expression on the left-hand side is inclusively + // within the range. + if (openRange->left().type->isSigned() || + expr.left().type->isSigned()) { + leftValue = builder.create(loc, lhs, lowBound); + } else { + leftValue = builder.create(loc, lhs, lowBound); + } + if (openRange->right().type->isSigned() || + expr.left().type->isSigned()) { + rightValue = builder.create(loc, lhs, highBound); + } else { + rightValue = builder.create(loc, lhs, highBound); + } + cond = builder.create(loc, leftValue, rightValue); + } else { + // Handle expressions. + if (!listExpr->type->isSimpleBitVector()) { + if (listExpr->type->isUnpackedArray()) { + mlir::emitError( + loc, "unpacked arrays in 'inside' expressions not supported"); + return {}; + } + mlir::emitError( + loc, "only simple bit vectors supported in 'inside' expressions"); + return {}; + } + auto value = + convertToSimpleBitVector(context.convertExpression(*listExpr)); + if (!value) + return {}; + cond = builder.create(loc, lhs, value); + } + conditions.push_back(cond); + } + + // Calculate the final result by `or` op. + auto result = conditions.back(); + conditions.pop_back(); + while (!conditions.empty()) { + result = builder.create(loc, conditions.back(), result); + conditions.pop_back(); + } + return result; + } + /// Emit an error for all other expressions. template Value visit(T &&node) { diff --git a/test/Conversion/ImportVerilog/basic.sv b/test/Conversion/ImportVerilog/basic.sv index a757c9ecb99a..35cbc8b8bf5b 100644 --- a/test/Conversion/ImportVerilog/basic.sv +++ b/test/Conversion/ImportVerilog/basic.sv @@ -544,6 +544,32 @@ module Expressions; // CHECK: moore.shr %u, %b : !moore.i32, !moore.i32 c = u >>> b; + // CHECK: moore.wildcard_eq %a, %a : !moore.i32 -> !moore.i1 + c = a inside { a }; + + // CHECK: [[TMP1:%.+]] = moore.wildcard_eq %a, %a : !moore.i32 -> !moore.i1 + // CHECK: [[TMP2:%.+]] = moore.wildcard_eq %a, %b : !moore.i32 -> !moore.i1 + // CHECK: moore.or [[TMP1]], [[TMP2]] : !moore.i1 + c = a inside { a, b }; + + // CHECK: [[TMP1:%.+]] = moore.wildcard_eq %a, %a : !moore.i32 -> !moore.i1 + // CHECK: [[TMP2:%.+]] = moore.wildcard_eq %a, %b : !moore.i32 -> !moore.i1 + // CHECK: [[TMP3:%.+]] = moore.wildcard_eq %a, %a : !moore.i32 -> !moore.i1 + // CHECK: [[TMP4:%.+]] = moore.wildcard_eq %a, %b : !moore.i32 -> !moore.i1 + // CHECK: [[TMP5:%.+]] = moore.or [[TMP3]], [[TMP4]] : !moore.i1 + // CHECK: [[TMP6:%.+]] = moore.or [[TMP2]], [[TMP5]] : !moore.i1 + // CHECK: moore.or [[TMP1]], [[TMP6]] : !moore.i1 + c = a inside { a, b, a, b }; + + // CHECK: [[TMP1:%.+]] = moore.wildcard_eq %a, %a : !moore.i32 -> !moore.i1 + // CHECK: [[TMP2:%.+]] = moore.wildcard_eq %a, %b : !moore.i32 -> !moore.i1 + // CHECK: [[TMP3:%.+]] = moore.sge %a, %a : !moore.i32 -> !moore.i1 + // CHECK: [[TMP4:%.+]] = moore.sle %a, %b : !moore.i32 -> !moore.i1 + // CHECK: [[TMP5:%.+]] = moore.and [[TMP3]], [[TMP4]] : !moore.i1 + // CHECK: [[TMP6:%.+]] = moore.or [[TMP2]], [[TMP5]] : !moore.i1 + // CHECK: moore.or [[TMP1]], [[TMP6]] : !moore.i1 + c = a inside { a, b, [a:b] }; + //===------------------------------------------------------------------===// // Assign operators diff --git a/test/Conversion/ImportVerilog/errors.sv b/test/Conversion/ImportVerilog/errors.sv index 65d74bd04509..4731f11c204b 100644 --- a/test/Conversion/ImportVerilog/errors.sv +++ b/test/Conversion/ImportVerilog/errors.sv @@ -177,3 +177,22 @@ module Foo; automatic int b; end endmodule + +// ----- + +module Foo; + int a, b, c; + bit d [3:0]; + initial begin + // expected-error @below {{literals with X or Z bits not supported}} + c = 'x inside { a }; + // expected-error @below {{literals with X or Z bits not supported}} + c = a inside { 'z, a }; + // expected-error @below {{literals with X or Z bits not supported}} + c = a inside { a, ['x:b] }; + // expected-error @below {{literals with X or Z bits not supported}} + c = a inside { a, [b:'z] }; + // expected-error @below {{unpacked arrays in 'inside' expressions not supported}} + c = a inside { d }; + end +endmodule