[ImportVerilog] Insert missing conversions around instance ports (#7647)

In certain corner cases, Slang does not insert the necessary conversion
AST nodes around instance ports. This can be problematic if an input or
output port is connected to a cast-compatible type (e.g. `i32` and
`array<1 x i32>`). To fix this, always insert conversions if the types
of a port and the connected value differ.
This commit is contained in:
Fabian Schuiki 2024-09-28 12:49:01 -07:00 committed by GitHub
parent a7f177312b
commit b86194929e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 3 deletions

View File

@ -394,6 +394,13 @@ struct ModuleVisitor : public BaseVisitor {
inputValues.push_back(value);
}
// Insert conversions for input ports.
for (auto [value, type] :
llvm::zip(inputValues, moduleType.getInputTypes()))
if (value.getType() != type)
value =
builder.create<moore::ConversionOp>(value.getLoc(), type, value);
// Create the instance op itself.
auto inputNames = builder.getArrayAttr(moduleType.getInputNames());
auto outputNames = builder.getArrayAttr(moduleType.getOutputNames());
@ -403,9 +410,15 @@ struct ModuleVisitor : public BaseVisitor {
inputNames, outputNames);
// Assign output values from the instance to the connected expression.
for (auto [lvalue, output] : llvm::zip(outputValues, inst.getOutputs()))
if (lvalue)
builder.create<moore::ContinuousAssignOp>(loc, lvalue, output);
for (auto [lvalue, output] : llvm::zip(outputValues, inst.getOutputs())) {
if (!lvalue)
continue;
Value rvalue = output;
auto dstType = cast<moore::RefType>(lvalue.getType()).getNestedType();
if (dstType != rvalue.getType())
rvalue = builder.create<moore::ConversionOp>(loc, dstType, rvalue);
builder.create<moore::ContinuousAssignOp>(loc, lvalue, rvalue);
}
return success();
}

View File

@ -2034,3 +2034,18 @@ package ParamPackage;
// CHECK: dbg.variable "ParamPackage::param2", [[TMP]] : !moore.i32
localparam int param2 = 9001;
endpackage
// CHECK-LABEL: moore.module @PortCastA()
module PortCastA;
bit [31:0] a, b;
// CHECK: [[TMP1:%.+]] = moore.read %a : <i32>
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.i32 -> !moore.array<1 x i32>
// CHECK: [[TMP3:%.+]] = moore.instance "sub" @PortCastB(a: [[TMP2]]: !moore.array<1 x i32>)
// CHECK: [[TMP4:%.+]] = moore.conversion [[TMP3]] : !moore.array<1 x i32> -> !moore.i32
// CHECK: moore.assign %b, [[TMP4]] : i32
PortCastB sub(a, b);
endmodule
module PortCastB (input bit [0:0][31:0] a, output bit [0:0][31:0] b);
assign b = a;
endmodule