mirror of https://github.com/llvm/circt.git
[ImportVerilog] Support set membership operator. (#7066)
This commit is contained in:
parent
9006a44b07
commit
851a1de172
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue