Skip to content

Commit

Permalink
[ImportVerilog] Support set membership operator. (#7066)
Browse files Browse the repository at this point in the history
  • Loading branch information
angelzzzzz authored May 23, 2024
1 parent 9006a44 commit 851a1de
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 0 deletions.
69 changes: 69 additions & 0 deletions lib/Conversion/ImportVerilog/Expressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Value> 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<slang::ast::OpenRangeExpression>()) {
// 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<moore::SgeOp>(loc, lhs, lowBound);
} else {
leftValue = builder.create<moore::UgeOp>(loc, lhs, lowBound);
}
if (openRange->right().type->isSigned() ||
expr.left().type->isSigned()) {
rightValue = builder.create<moore::SleOp>(loc, lhs, highBound);
} else {
rightValue = builder.create<moore::UleOp>(loc, lhs, highBound);
}
cond = builder.create<moore::AndOp>(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<moore::WildcardEqOp>(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<moore::OrOp>(loc, conditions.back(), result);
conditions.pop_back();
}
return result;
}

/// Emit an error for all other expressions.
template <typename T>
Value visit(T &&node) {
Expand Down
26 changes: 26 additions & 0 deletions test/Conversion/ImportVerilog/basic.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
19 changes: 19 additions & 0 deletions test/Conversion/ImportVerilog/errors.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 851a1de

Please sign in to comment.