mirror of https://github.com/llvm/circt.git
[ImportVerilog] Add missing conversions, various fixes
Add missing conversions for cases where the Slang AST has expressions operating directly on packed structs/arrays, but the Moore IR expects a conversion to a simple bit vector type. Also clean up a few things and remove an invalid `struct_inject` conversion.
This commit is contained in:
parent
20cb546d18
commit
272af6c158
|
@ -28,10 +28,21 @@ struct RvalueExprVisitor {
|
|||
Value convertToSimpleBitVector(Value value) {
|
||||
if (!value)
|
||||
return {};
|
||||
if (isa<moore::IntType>(value.getType()) ||
|
||||
isa<moore::IntType>(
|
||||
dyn_cast<moore::RefType>(value.getType()).getNestedType()))
|
||||
if (isa<moore::IntType>(value.getType()))
|
||||
return value;
|
||||
|
||||
// Some operations in Slang's AST, for example bitwise or `|`, don't cast
|
||||
// packed struct/array operands to simple bit vectors but directly operate
|
||||
// on the struct/array. Since the corresponding IR ops operate only on
|
||||
// simple bit vectors, insert a conversion in this case.
|
||||
if (auto packed = dyn_cast<moore::PackedType>(value.getType())) {
|
||||
if (auto bits = packed.getBitSize()) {
|
||||
auto sbvType =
|
||||
moore::IntType::get(value.getContext(), *bits, packed.getDomain());
|
||||
return builder.create<moore::ConversionOp>(loc, sbvType, value);
|
||||
}
|
||||
}
|
||||
|
||||
mlir::emitError(loc, "expression of type ")
|
||||
<< value.getType() << " cannot be cast to a simple bit vector";
|
||||
return {};
|
||||
|
@ -55,16 +66,14 @@ struct RvalueExprVisitor {
|
|||
Value visit(const slang::ast::LValueReferenceExpression &expr) {
|
||||
assert(!context.lvalueStack.empty() && "parent assignments push lvalue");
|
||||
auto lvalue = context.lvalueStack.back();
|
||||
return builder.create<moore::ReadOp>(
|
||||
loc, cast<moore::RefType>(lvalue.getType()).getNestedType(), lvalue);
|
||||
return builder.create<moore::ReadOp>(loc, lvalue);
|
||||
}
|
||||
|
||||
// Handle named values, such as references to declared variables.
|
||||
Value visit(const slang::ast::NamedValueExpression &expr) {
|
||||
if (auto value = context.valueSymbols.lookup(&expr.symbol)) {
|
||||
if (auto refType = dyn_cast<moore::RefType>(value.getType()))
|
||||
value =
|
||||
builder.create<moore::ReadOp>(loc, refType.getNestedType(), value);
|
||||
if (isa<moore::RefType>(value.getType()))
|
||||
value = builder.create<moore::ReadOp>(loc, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -92,19 +101,20 @@ struct RvalueExprVisitor {
|
|||
auto type = context.convertType(*expr.type);
|
||||
if (!type)
|
||||
return {};
|
||||
auto operand = context.convertRvalueExpression(expr.operand());
|
||||
if (!operand)
|
||||
return {};
|
||||
return builder.create<moore::ConversionOp>(loc, type, operand);
|
||||
return context.convertRvalueExpression(expr.operand(), type);
|
||||
}
|
||||
|
||||
// Handle blocking and non-blocking assignments.
|
||||
Value visit(const slang::ast::AssignmentExpression &expr) {
|
||||
auto lhs = context.convertLvalueExpression(expr.left());
|
||||
if (!lhs)
|
||||
return {};
|
||||
|
||||
context.lvalueStack.push_back(lhs);
|
||||
auto rhs = context.convertRvalueExpression(expr.right());
|
||||
auto rhs = context.convertRvalueExpression(
|
||||
expr.right(), cast<moore::RefType>(lhs.getType()).getNestedType());
|
||||
context.lvalueStack.pop_back();
|
||||
if (!lhs || !rhs)
|
||||
if (!rhs)
|
||||
return {};
|
||||
|
||||
if (expr.timingControl) {
|
||||
|
@ -135,12 +145,7 @@ struct RvalueExprVisitor {
|
|||
|
||||
// Helper function to create pre and post increments and decrements.
|
||||
Value createIncrement(Value arg, bool isInc, bool isPost) {
|
||||
auto preValue = convertToSimpleBitVector(arg);
|
||||
if (!preValue)
|
||||
return {};
|
||||
preValue = builder.create<moore::ReadOp>(
|
||||
loc, cast<moore::RefType>(preValue.getType()).getNestedType(),
|
||||
preValue);
|
||||
auto preValue = builder.create<moore::ReadOp>(loc, arg);
|
||||
auto one = builder.create<moore::ConstantOp>(
|
||||
loc, cast<moore::IntType>(preValue.getType()), 1);
|
||||
auto postValue =
|
||||
|
@ -220,8 +225,10 @@ struct RvalueExprVisitor {
|
|||
template <class ConcreteOp>
|
||||
Value createBinary(Value lhs, Value rhs) {
|
||||
lhs = convertToSimpleBitVector(lhs);
|
||||
if (!lhs)
|
||||
return {};
|
||||
rhs = convertToSimpleBitVector(rhs);
|
||||
if (!lhs || !rhs)
|
||||
if (!rhs)
|
||||
return {};
|
||||
return builder.create<ConcreteOp>(loc, lhs, rhs);
|
||||
}
|
||||
|
@ -229,8 +236,10 @@ struct RvalueExprVisitor {
|
|||
// Handle binary operators.
|
||||
Value visit(const slang::ast::BinaryExpression &expr) {
|
||||
auto lhs = context.convertRvalueExpression(expr.left());
|
||||
if (!lhs)
|
||||
return {};
|
||||
auto rhs = context.convertRvalueExpression(expr.right());
|
||||
if (!lhs || !rhs)
|
||||
if (!rhs)
|
||||
return {};
|
||||
|
||||
using slang::ast::BinaryOperator;
|
||||
|
@ -904,9 +913,13 @@ struct LvalueExprVisitor {
|
|||
};
|
||||
} // namespace
|
||||
|
||||
Value Context::convertRvalueExpression(const slang::ast::Expression &expr) {
|
||||
Value Context::convertRvalueExpression(const slang::ast::Expression &expr,
|
||||
Type requiredType) {
|
||||
auto loc = convertLocation(expr.sourceRange);
|
||||
return expr.visit(RvalueExprVisitor(*this, loc));
|
||||
auto value = expr.visit(RvalueExprVisitor(*this, loc));
|
||||
if (value && requiredType && value.getType() != requiredType)
|
||||
value = builder.create<moore::ConversionOp>(loc, requiredType, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
Value Context::convertLvalueExpression(const slang::ast::Expression &expr) {
|
||||
|
|
|
@ -88,7 +88,8 @@ struct Context {
|
|||
LogicalResult convertStatement(const slang::ast::Statement &stmt);
|
||||
|
||||
// Convert an expression AST node to MLIR ops.
|
||||
Value convertRvalueExpression(const slang::ast::Expression &expr);
|
||||
Value convertRvalueExpression(const slang::ast::Expression &expr,
|
||||
Type requiredType = {});
|
||||
Value convertLvalueExpression(const slang::ast::Expression &expr);
|
||||
|
||||
// Convert a slang timing control into an MLIR timing control.
|
||||
|
|
|
@ -364,7 +364,7 @@ struct ModuleVisitor : public BaseVisitor {
|
|||
|
||||
Value initial;
|
||||
if (const auto *init = varNode.getInitializer()) {
|
||||
initial = context.convertRvalueExpression(*init);
|
||||
initial = context.convertRvalueExpression(*init, loweredType);
|
||||
if (!initial)
|
||||
return failure();
|
||||
}
|
||||
|
@ -384,7 +384,8 @@ struct ModuleVisitor : public BaseVisitor {
|
|||
|
||||
Value assignment;
|
||||
if (netNode.getInitializer()) {
|
||||
assignment = context.convertRvalueExpression(*netNode.getInitializer());
|
||||
assignment = context.convertRvalueExpression(*netNode.getInitializer(),
|
||||
loweredType);
|
||||
if (!assignment)
|
||||
return failure();
|
||||
}
|
||||
|
@ -413,21 +414,14 @@ struct ModuleVisitor : public BaseVisitor {
|
|||
|
||||
const auto &expr =
|
||||
assignNode.getAssignment().as<slang::ast::AssignmentExpression>();
|
||||
|
||||
auto lhs = context.convertLvalueExpression(expr.left());
|
||||
auto rhs = context.convertRvalueExpression(expr.right());
|
||||
if (!lhs || !rhs)
|
||||
if (!lhs)
|
||||
return failure();
|
||||
|
||||
if (auto refOp = lhs.getDefiningOp<moore::StructExtractRefOp>()) {
|
||||
auto input = refOp.getInput();
|
||||
if (isa<moore::SVModuleOp>(input.getDefiningOp()->getParentOp())) {
|
||||
builder.create<moore::StructInjectOp>(loc, input.getType(), input,
|
||||
refOp.getFieldNameAttr(), rhs);
|
||||
refOp->erase();
|
||||
return success();
|
||||
}
|
||||
}
|
||||
auto rhs = context.convertRvalueExpression(
|
||||
expr.right(), cast<moore::RefType>(lhs.getType()).getNestedType());
|
||||
if (!rhs)
|
||||
return failure();
|
||||
|
||||
builder.create<moore::ContinuousAssignOp>(loc, lhs, rhs);
|
||||
return success();
|
||||
|
|
|
@ -214,6 +214,21 @@ module Basic;
|
|||
string s1;
|
||||
assign s1 = "Hello World";
|
||||
|
||||
typedef struct packed { bit x; bit y; } MyStruct;
|
||||
// CHECK: [[VAR_S2:%.+]] = moore.variable : <struct<{x: i1, y: i1}>>
|
||||
MyStruct s2;
|
||||
// CHECK: [[TMP1:%.+]] = moore.read [[VAR_S2]]
|
||||
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.struct<{x: i1, y: i1}> -> !moore.i2
|
||||
// CHECK: [[TMP3:%.+]] = moore.not [[TMP2]] : i2
|
||||
// CHECK: [[TMP4:%.+]] = moore.conversion [[TMP3]] : !moore.i2 -> !moore.struct<{x: i1, y: i1}>
|
||||
// CHECK: moore.assign [[VAR_S2]], [[TMP4]]
|
||||
assign s2 = ~s2;
|
||||
// CHECK: [[TMP1:%.+]] = moore.read [[VAR_S2]]
|
||||
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.struct<{x: i1, y: i1}> -> !moore.i2
|
||||
// CHECK: [[TMP3:%.+]] = moore.not [[TMP2]] : i2
|
||||
// CHECK: [[TMP4:%.+]] = moore.conversion [[TMP3]] : !moore.i2 -> !moore.struct<{x: i1, y: i1}>
|
||||
// CHECK: [[VAR_S3:%.+]] = moore.variable [[TMP4]] : <struct<{x: i1, y: i1}>>
|
||||
MyStruct s3 = ~s2;
|
||||
endmodule
|
||||
|
||||
// CHECK-LABEL: moore.module @Statements
|
||||
|
@ -594,8 +609,7 @@ module Expressions;
|
|||
c = -a;
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %v
|
||||
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.array<2 x i4> -> !moore.i32
|
||||
// CHECK: [[TMP3:%.+]] = moore.neg [[TMP2]] : i32
|
||||
// CHECK: [[TMP4:%.+]] = moore.conversion [[TMP3]] : !moore.i32 -> !moore.i32
|
||||
// CHECK: moore.neg [[TMP2]] : i32
|
||||
c = -v;
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %a
|
||||
// CHECK: moore.not [[TMP1]] : i32
|
||||
|
@ -665,10 +679,9 @@ module Expressions;
|
|||
// CHECK: moore.add [[TMP1]], [[TMP2]] : i32
|
||||
c = a + b;
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %a
|
||||
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.i32 -> !moore.i32
|
||||
// CHECK: [[TMP3:%.+]] = moore.read %v
|
||||
// CHECK: [[TMP4:%.+]] = moore.conversion [[TMP3]] : !moore.array<2 x i4> -> !moore.i32
|
||||
// CHECK: moore.add [[TMP2]], [[TMP4]] : i32
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %v
|
||||
// CHECK: [[TMP3:%.+]] = moore.conversion [[TMP2]] : !moore.array<2 x i4> -> !moore.i32
|
||||
// CHECK: moore.add [[TMP1]], [[TMP3]] : i32
|
||||
c = a + v;
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %a
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %b
|
||||
|
@ -1080,11 +1093,9 @@ module Conversion;
|
|||
|
||||
// Sign conversion.
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %b
|
||||
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.i32 -> !moore.i32
|
||||
// CHECK: %d1 = moore.variable [[TMP2]]
|
||||
// CHECK: [[TMP3:%.+]] = moore.read %b
|
||||
// CHECK: [[TMP4:%.+]] = moore.conversion [[TMP3]] : !moore.i32 -> !moore.i32
|
||||
// CHECK: %d2 = moore.variable [[TMP4]]
|
||||
// CHECK: %d1 = moore.variable [[TMP1]]
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %b
|
||||
// CHECK: %d2 = moore.variable [[TMP2]]
|
||||
bit signed [31:0] d1 = signed'(b);
|
||||
bit [31:0] d2 = unsigned'(b);
|
||||
|
||||
|
|
Loading…
Reference in New Issue