Skip to content

Commit 53a427d

Browse files
committed
[FIRRTL] Change firrtl-lower-xmr to a walk
Change the way that the `LowerXMR` pass visits operations in modules from just visiting operations in the body to a walk. This is done to fix a bug exposed when compiling inline layers that define probes. Previously, operations inside the `sv.ifdef` that this lowering creates are not visited resulting in a `LowerXMR` pass failure. This change future-proofs this pass so that any new operations added to FIRRTL which may include regions and blocks will do something sane. This also makes the pass more relocatable within the FIRRTL pass pipeline. Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
1 parent 383e4aa commit 53a427d

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

lib/Dialect/FIRRTL/Transforms/LowerXMR.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ class LowerXMRPass : public circt::firrtl::impl::LowerXMRBase<LowerXMRPass> {
9595
SmallVector<Operation *> forceAndReleaseOps;
9696
// The dataflow function, that propagates the reachable RefSendOp across
9797
// RefType Ops.
98-
auto transferFunc = [&](Operation &op) -> LogicalResult {
99-
return TypeSwitch<Operation *, LogicalResult>(&op)
98+
auto transferFunc = [&](Operation *op) -> LogicalResult {
99+
return TypeSwitch<Operation *, LogicalResult>(op)
100100
.Case<RefSendOp>([&](RefSendOp send) {
101101
// Get a reference to the actual signal to which the XMR will be
102102
// generated.
@@ -266,9 +266,14 @@ class LowerXMRPass : public circt::firrtl::impl::LowerXMRBase<LowerXMRPass> {
266266
if (module.isPublic())
267267
publicModules.push_back(module);
268268

269-
for (Operation &op : module.getBodyBlock()->getOperations())
269+
auto result = module.walk([&](Operation *op) {
270270
if (transferFunc(op).failed())
271-
return signalPassFailure();
271+
return WalkResult::interrupt();
272+
return WalkResult::advance();
273+
});
274+
275+
if (result.wasInterrupted())
276+
return signalPassFailure();
272277

273278
// Clear any enabled layers.
274279
module.setLayersAttr(ArrayAttr::get(module.getContext(), {}));

test/Dialect/FIRRTL/lowerXMR.mlir

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,3 +780,22 @@ firrtl.circuit "WireProbe" {
780780
firrtl.ref.define %p, %w : !firrtl.probe<uint<5>>
781781
}
782782
}
783+
784+
// -----
785+
// Test that operations with regions and blocks are visited. This will error if
786+
// blocks are not visited.
787+
788+
// CHECK-LABEL: "Foo"
789+
firrtl.circuit "Foo" {
790+
// CHECK: hierpath {{.*}} [@Foo::@[[SYM:[^ ]+]]]
791+
sv.macro.decl @A
792+
firrtl.module @Foo(out %a: !firrtl.probe<uint<1>>) {
793+
//CHECK: sv.ifdef
794+
sv.ifdef @A {
795+
%b = firrtl.wire : !firrtl.uint<1>
796+
// CHECK: firrtl.node sym @[[SYM]] {{.*}} %b
797+
%0 = firrtl.ref.send %b : !firrtl.uint<1>
798+
firrtl.ref.define %a, %0 : !firrtl.probe<uint<1>>
799+
}
800+
}
801+
}

0 commit comments

Comments
 (0)