[HW] Fix creating modules with InOut typed ports

When we create the PortInfo object for a module, if the port is a
HW::InOutType, we strip it and set the isInOut field to true.  When we create a
module from a PortInfo object we respect this field while constructing the
function type, but were not respecting the isInOut when creating the block
arguments.

This change starts respecting the `isInOut` field of port info when
constructing the block argument types.  This also adds a verifier that the
function type of the module matches the block argument types.
This commit is contained in:
Andrew Young 2023-01-24 09:53:33 -08:00
parent 2417e7f403
commit 321948dc3d
2 changed files with 30 additions and 3 deletions

View File

@ -747,8 +747,12 @@ void HWModuleOp::build(OpBuilder &builder, OperationState &result,
bodyRegion->push_back(body);
// Add arguments to the body block.
for (auto elt : ports.inputs)
body->addArgument(elt.type, builder.getUnknownLoc());
for (auto port : ports.inputs) {
auto type = port.type;
if (port.isInOut() && !type.isa<InOutType>())
type = InOutType::get(type);
body->addArgument(type, builder.getUnknownLoc());
}
if (shouldEnsureTerminator)
HWModuleOp::ensureTerminator(*bodyRegion, builder, result.location);
@ -1204,7 +1208,25 @@ static LogicalResult verifyModuleCommon(Operation *module) {
return success();
}
LogicalResult HWModuleOp::verify() { return verifyModuleCommon(*this); }
LogicalResult HWModuleOp::verify() {
if (failed(verifyModuleCommon(*this)))
return failure();
auto type = getFunctionType();
auto *body = getBodyBlock();
// Verify the number of block arguments.
auto numInputs = type.getNumInputs();
if (body->getNumArguments() != numInputs)
return emitOpError("entry block must have")
<< numInputs << " arguments to match module signature";
// Verify that the block arguments match the op's attributes.
for (auto [arg, type] : llvm::zip(getArguments(), type.getInputs()))
if (arg.getType() != type)
return emitOpError("block argument types should match signature types");
return success();
}
LogicalResult HWModuleExternOp::verify() { return verifyModuleCommon(*this); }

View File

@ -153,6 +153,11 @@ hw.module @signed_arrays(%arg0: si8) -> (out: !hw.array<2xsi8>) {
hw.output %result : !hw.array<2xsi8>
}
// Check that we pass the verifier that the module's function type matches
// the block argument types when using InOutTypes.
// CHECK: hw.module @InOutPort(%arg0: !hw.inout<i1>)
hw.module @InOutPort(%arg0: !hw.inout<i1>) -> () { }
/// Port names that aren't valid MLIR identifiers are handled with `argNames`
/// attribute being explicitly printed.
// https://github.com/llvm/circt/issues/1822