Skip to content

Commit 8916574

Browse files
committed
[FIRRTL] EliminateWires: preserve sv.attributes when converting WireOp to NodeOp
When LowerAnnotations processes firrtl.AttributeAnnotation (the mechanism used by Chisel's addAttribute()), it sets sv.attributes on the FIRRTL WireOp. EliminateWires then converts single-writer passive WireOps to NodeOps without copying sv.attributes, causing attributes like mark_debug to be silently dropped before LowerToHW runs. Copy sv.attributes from the WireOp to the replacement NodeOp, matching the existing pattern in LowerToHW.cpp for RegOp and RegResetOp. Assisted-by: vscode/eicp:Claude Opus 4.6
1 parent 5306f6f commit 8916574

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

lib/Dialect/FIRRTL/Transforms/EliminateWires.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "circt/Dialect/FIRRTL/FIRRTLOps.h"
1717
#include "circt/Dialect/FIRRTL/Passes.h"
18+
#include "circt/Dialect/SV/SVAttributes.h"
1819
#include "circt/Support/Debug.h"
1920
#include "mlir/IR/Dominance.h"
2021
#include "mlir/IR/ImplicitLocOpBuilder.h"
@@ -87,6 +88,12 @@ void EliminateWiresPass::runOnOperation() {
8788
auto node = NodeOp::create(builder, writer.getSrc(), wire.getName(),
8889
wire.getNameKind(), wire.getAnnotations(),
8990
wire.getInnerSymAttr(), wire.getForceable());
91+
// Preserve sv.attributes (e.g. mark_debug) set by LowerAnnotations from
92+
// firrtl.AttributeAnnotation. Without this, the attributes are silently
93+
// dropped when a WireOp is converted to a NodeOp, causing addAttribute()
94+
// annotations to never appear in the emitted SV.
95+
if (auto svAttrs = sv::getSVAttributes(wire))
96+
sv::setSVAttributes(node, svAttrs);
9097
wire.replaceAllUsesWith(node);
9198
wire.erase();
9299
writer.erase();

test/Dialect/FIRRTL/eliminate-wires.mlir

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
firrtl.circuit "TopLevel" {
44

55
// CHECK-LABEL: @TopLevel
6-
firrtl.module @TopLevel(in %source: !firrtl.uint<1>,
6+
firrtl.module @TopLevel(in %source: !firrtl.uint<1>,
77
out %sink: !firrtl.uint<1>) {
88
// CHECK-NOT: firrtl.wire
99
%w = firrtl.wire : !firrtl.uint<1>
@@ -26,4 +26,19 @@ firrtl.circuit "TopLevel" {
2626
// CHECK-NEXT: %b = firrtl.node %[[inv]] : !firrtl.uint<3>
2727
// CHECK-NEXT: %a = firrtl.node %b : !firrtl.uint<3>
2828
}
29+
30+
// CHECK-LABEL: @SvAttributesPreserved
31+
// Verify that sv.attributes set on a wire are propagated to the replacement
32+
// NodeOp. Previously EliminateWires dropped sv.attributes, causing
33+
// firrtl.AttributeAnnotation (Chisel's addAttribute()) to produce no output
34+
// in emitted SV.
35+
firrtl.module private @SvAttributesPreserved(in %source: !firrtl.uint<1>,
36+
out %sink: !firrtl.uint<1>) {
37+
// CHECK-NOT: firrtl.wire
38+
// CHECK: %w = firrtl.node
39+
// CHECK-SAME: sv.attributes = [#sv.attribute<"mark_debug = \22true\22">]
40+
%w = firrtl.wire {sv.attributes = [#sv.attribute<"mark_debug = \"true\"">]} : !firrtl.uint<1>
41+
firrtl.matchingconnect %w, %source : !firrtl.uint<1>
42+
firrtl.matchingconnect %sink, %w : !firrtl.uint<1>
43+
}
2944
}

0 commit comments

Comments
 (0)