diff --git a/lib/Conversion/ImportVerilog/Expressions.cpp b/lib/Conversion/ImportVerilog/Expressions.cpp index 6f0706ef155a..f62471b3f49b 100644 --- a/lib/Conversion/ImportVerilog/Expressions.cpp +++ b/lib/Conversion/ImportVerilog/Expressions.cpp @@ -522,7 +522,6 @@ struct RvalueExprVisitor { // 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 = @@ -549,26 +548,41 @@ struct RvalueExprVisitor { } else { rightValue = builder.create(loc, lhs, highBound); } - cond = builder.create(loc, leftValue, rightValue); + conditions.push_back( + builder.create(loc, leftValue, rightValue)); } else { // Handle expressions. if (!listExpr->type->isSimpleBitVector()) { if (listExpr->type->isUnpackedArray()) { + if (listExpr->type->isFixedSize()) { + const auto &uaType = + listExpr->type->as(); + auto value = context.convertRvalueExpression(*listExpr); + if (!value) + return {}; + if (failed(context.collectConditionsForUnpackedArray( + uaType, value, conditions, lhs, loc))) + return {}; + } else { + mlir::emitError(loc, "unsized unpacked arrays in 'inside' " + "expressions not supported"); + return {}; + } + } else { mlir::emitError( - loc, "unpacked arrays in 'inside' expressions not supported"); + loc, + "only simple bit vectors supported in 'inside' expressions"); return {}; } - mlir::emitError( - loc, "only simple bit vectors supported in 'inside' expressions"); - return {}; + } else { + auto value = context.convertToSimpleBitVector( + context.convertRvalueExpression(*listExpr)); + if (!value) + return {}; + conditions.push_back( + builder.create(loc, lhs, value)); } - auto value = context.convertToSimpleBitVector( - context.convertRvalueExpression(*listExpr)); - if (!value) - return {}; - cond = builder.create(loc, lhs, value); } - conditions.push_back(cond); } // Calculate the final result by `or` op. @@ -1101,3 +1115,39 @@ Value Context::materializeConversion(Type type, Value value, bool isSigned, value = builder.create(loc, type, value); return value; } + +LogicalResult Context::collectConditionsForUnpackedArray( + const slang::ast::FixedSizeUnpackedArrayType &slangType, + Value upackedArrayValue, SmallVector &conditions, Value lhs, + Location loc) { + auto type = convertType(slangType); + if (!type) { + return failure(); + } + auto mooreType = dyn_cast(type); + const auto &elementType = slangType.elementType; + for (slang::int32_t i = slangType.getFixedRange().lower(); + i <= slangType.getFixedRange().upper(); i++) { + auto elemValue = builder.create( + loc, mooreType.getElementType(), upackedArrayValue, i); + if (elementType.isUnpackedArray()) { + if (failed(collectConditionsForUnpackedArray( + elementType.as(), + elemValue, conditions, lhs, loc))) { + return failure(); + } + } else if (elementType.isSingular()) { + if (elementType.isIntegral()) { + conditions.push_back( + builder.create(loc, lhs, elemValue)); + } else { + conditions.push_back(builder.create(loc, lhs, elemValue)); + } + } else { + assert(false && "Slang guarantees only singular values and fixed-size " + "unpacked arrays allowed as elements of unpacked arrays " + "in 'inside' expressions"); + } + } + return success(); +} diff --git a/lib/Conversion/ImportVerilog/ImportVerilogInternals.h b/lib/Conversion/ImportVerilog/ImportVerilogInternals.h index b045ffe00713..c5acc3abd151 100644 --- a/lib/Conversion/ImportVerilog/ImportVerilogInternals.h +++ b/lib/Conversion/ImportVerilog/ImportVerilogInternals.h @@ -135,6 +135,13 @@ struct Context { Value materializeConstant(const slang::ConstantValue &constant, const slang::ast::Type &type, Location loc); + /// Helper function to construct conditions for a fixed-size unpacked array in + /// an `inside` expression. + LogicalResult collectConditionsForUnpackedArray( + const slang::ast::FixedSizeUnpackedArrayType &slangType, + Value upackedArrayValue, SmallVector &conditions, Value lhs, + Location loc); + /// Convert a list of string literal arguments with formatting specifiers and /// arguments to be interpolated into a `!moore.format_string` value. Returns /// failure if an error occurs. Returns a null value if the formatted string diff --git a/test/Conversion/ImportVerilog/basic.sv b/test/Conversion/ImportVerilog/basic.sv index c2e9630e0ab5..33437cd42275 100644 --- a/test/Conversion/ImportVerilog/basic.sv +++ b/test/Conversion/ImportVerilog/basic.sv @@ -657,6 +657,10 @@ module Expressions; bit [31:0] uarrayInt [2]; // CHECK: %m = moore.variable : logic [3:0] m; + // CHECK: %ua = moore.variable : > + int ua[3]; + // CHECK: %ua2d = moore.variable : >> + int ua2d[2][2]; initial begin // CHECK: moore.constant 0 : i32 @@ -1076,6 +1080,35 @@ module Expressions; // CHECK: moore.or [[TMP3]], [[TMP11]] : i1 c = a inside { a, b, [a:b] }; + // CHECK: [[TMP1:%.+]] = moore.read %a : + // CHECK: [[TMP2:%.+]] = moore.read %ua : > + // CHECK: [[TMP3:%.+]] = moore.extract [[TMP2]] from 0 : uarray<3 x i32> -> i32 + // CHECK: [[TMP4:%.+]] = moore.wildcard_eq [[TMP1]], [[TMP3]] : i32 -> i1 + // CHECK: [[TMP5:%.+]] = moore.extract [[TMP2]] from 1 : uarray<3 x i32> -> i32 + // CHECK: [[TMP6:%.+]] = moore.wildcard_eq [[TMP1]], [[TMP5]] : i32 -> i1 + // CHECK: [[TMP7:%.+]] = moore.extract [[TMP2]] from 2 : uarray<3 x i32> -> i32 + // CHECK: [[TMP8:%.+]] = moore.wildcard_eq [[TMP1]], [[TMP7]] : i32 -> i1 + // CHECK: [[TMP9:%.+]] = moore.or [[TMP6]], [[TMP8]] : i1 + // CHECK: [[TMP10:%.+]] = moore.or [[TMP4]], [[TMP9]] : i1 + c = a inside { ua }; + + // CHECK: [[TMP1:%.+]] = moore.read %a : + // CHECK: [[TMP2:%.+]] = moore.read %ua2d : >> + // CHECK: [[TMP3:%.+]] = moore.extract [[TMP2]] from 0 : uarray<2 x uarray<2 x i32>> -> uarray<2 x i32> + // CHECK: [[TMP4:%.+]] = moore.extract [[TMP3]] from 0 : uarray<2 x i32> -> i32 + // CHECK: [[TMP5:%.+]] = moore.wildcard_eq [[TMP1]], [[TMP4]] : i32 -> i1 + // CHECK: [[TMP6:%.+]] = moore.extract [[TMP3]] from 1 : uarray<2 x i32> -> i32 + // CHECK: [[TMP7:%.+]] = moore.wildcard_eq [[TMP1]], [[TMP6]] : i32 -> i1 + // CHECK: [[TMP8:%.+]] = moore.extract [[TMP2]] from 1 : uarray<2 x uarray<2 x i32>> -> uarray<2 x i32> + // CHECK: [[TMP9:%.+]] = moore.extract [[TMP8]] from 0 : uarray<2 x i32> -> i32 + // CHECK: [[TMP10:%.+]] = moore.wildcard_eq [[TMP1]], [[TMP9]] : i32 -> i1 + // CHECK: [[TMP11:%.+]] = moore.extract [[TMP8]] from 1 : uarray<2 x i32> -> i32 + // CHECK: [[TMP12:%.+]] = moore.wildcard_eq [[TMP1]], [[TMP11]] : i32 -> i1 + // CHECK: [[TMP13:%.+]] = moore.or [[TMP10]], [[TMP12]] : i1 + // CHECK: [[TMP14:%.+]] = moore.or [[TMP7]], [[TMP13]] : i1 + // CHECK: [[TMP15:%.+]] = moore.or [[TMP5]], [[TMP14]] : i1 + c = a inside { ua2d }; + //===------------------------------------------------------------------===// // Conditional operator diff --git a/test/Conversion/ImportVerilog/errors.sv b/test/Conversion/ImportVerilog/errors.sv index a9c310752c05..ce3bd371a909 100644 --- a/test/Conversion/ImportVerilog/errors.sv +++ b/test/Conversion/ImportVerilog/errors.sv @@ -68,8 +68,8 @@ endmodule // ----- module Foo; - int a, b[3]; - // expected-error @below {{unpacked arrays in 'inside' expressions not supported}} + int a, b[]; + // expected-error @below {{unsized unpacked arrays in 'inside' expressions not supported}} int c = a inside { b }; endmodule