diff --git a/lib/Dialect/FIRRTL/FIRRTLOps.cpp b/lib/Dialect/FIRRTL/FIRRTLOps.cpp index 2304c4700512..2bd57ae9aa2f 100644 --- a/lib/Dialect/FIRRTL/FIRRTLOps.cpp +++ b/lib/Dialect/FIRRTL/FIRRTLOps.cpp @@ -6193,10 +6193,30 @@ LogicalResult RWProbeOp::verifyInnerRefs(hw::InnerRefNamespace &ns) { } return success(); }; + + auto checkLayers = [&](Location loc) -> LogicalResult { + auto dstLayers = getAmbientLayersAt(target.getOp()); + auto srcLayers = getLayersFor(getResult()); + SmallVector missingLayers; + if (!isLayerSetCompatibleWith(srcLayers, dstLayers, missingLayers)) { + auto diag = emitOpError("target has insufficient layer requirements"); + auto ¬e = diag.attachNote(loc); + note << "target is missing layer requirements: "; + llvm::interleaveComma(missingLayers, note); + return failure(); + } + return success(); + }; + auto checks = [&](auto type, Location loc) { + if (failed(checkLayers(loc))) + return failure(); + return checkFinalType(type, loc); + }; + if (target.isPort()) { auto mod = cast(target.getOp()); - return checkFinalType(mod.getPortType(target.getPort()), - mod.getPortLocation(target.getPort())); + return checks(mod.getPortType(target.getPort()), + mod.getPortLocation(target.getPort())); } hw::InnerSymbolOpInterface symOp = cast(target.getOp()); @@ -6210,7 +6230,7 @@ LogicalResult RWProbeOp::verifyInnerRefs(hw::InnerRefNamespace &ns) { return emitOpError("is not dominated by target") .attachNote(symOp.getLoc()) .append("target here"); - return checkFinalType(symOp.getTargetResult().getType(), symOp.getLoc()); + return checks(symOp.getTargetResult().getType(), symOp.getLoc()); } //===----------------------------------------------------------------------===// diff --git a/test/Dialect/FIRRTL/errors.mlir b/test/Dialect/FIRRTL/errors.mlir index df380bb419d7..98faab098ef4 100644 --- a/test/Dialect/FIRRTL/errors.mlir +++ b/test/Dialect/FIRRTL/errors.mlir @@ -2072,6 +2072,20 @@ firrtl.circuit "RWProbeUseDef" { // ----- +firrtl.circuit "RWProbeLayerRequirements" { + firrtl.layer @A bind { } + firrtl.module @RWProbeLayerRequirements(in %cond : !firrtl.uint<1>) { + // expected-note @below {{target is missing layer requirements: @A}} + %w = firrtl.wire sym @x : !firrtl.uint<1> + firrtl.layerblock @A { + // expected-error @below {{target has insufficient layer requirements}} + %rw = firrtl.ref.rwprobe <@RWProbeLayerRequirements::@x> : !firrtl.rwprobe> + } + } +} + +// ----- + firrtl.circuit "MissingClassForObjectPortInModule" { // expected-error @below {{'firrtl.module' op references unknown class @Missing}} firrtl.module @MissingClassForObjectPortInModule(out %o: !firrtl.class<@Missing()>) {} diff --git a/test/Dialect/FIRRTL/layers.mlir b/test/Dialect/FIRRTL/layers.mlir index 472b171a9a43..23567729cda7 100644 --- a/test/Dialect/FIRRTL/layers.mlir +++ b/test/Dialect/FIRRTL/layers.mlir @@ -201,4 +201,16 @@ firrtl.circuit "Test" { firrtl.propassign %foo_in, %str : !firrtl.string } } + + //===--------------------------------------------------------------------===// + // RWProbe under Layer + //===--------------------------------------------------------------------===// + + firrtl.module @RWProbeInLayer() { + firrtl.layerblock @A { + %w = firrtl.wire sym @sym : !firrtl.uint<1> + %rwp = firrtl.ref.rwprobe <@RWProbeInLayer::@sym> : !firrtl.rwprobe> + } + } + }