diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc index 99a223bdc..2cd845bdf 100644 --- a/passes/cmds/setundef.cc +++ b/passes/cmds/setundef.cc @@ -355,6 +355,28 @@ struct SetundefPass : public Pass { bits.append(worker.next_bit()); module->connect(RTLIL::SigSig(c, bits)); } + // Remove init attributes from undriven wires to prevent + // conflicts with the values we just assigned (issue #5835). + for (auto &c : sig.chunks()) { + if (c.wire && c.wire->attributes.count(ID::init)) { + if (c.wire->width == c.width && c.offset == 0) { + c.wire->attributes.erase(ID::init); + log("Removing init attribute from undriven wire %s.\n", log_id(c.wire)); + } else { + Const &initval = c.wire->attributes[ID::init]; + initval.resize(GetSize(c.wire), State::Sx); + for (int i = c.offset; i < c.offset + c.width; i++) + initval.set(i, State::Sx); + if (initval.is_fully_undef()) { + c.wire->attributes.erase(ID::init); + log("Removing init attribute from undriven wire %s.\n", log_id(c.wire)); + } else { + log("Clearing init attribute bits [%d:%d] from partially undriven wire %s.\n", + c.offset + c.width - 1, c.offset, log_id(c.wire)); + } + } + } + } } } diff --git a/tests/various/setundef_init.ys b/tests/various/setundef_init.ys new file mode 100644 index 000000000..db5b80783 --- /dev/null +++ b/tests/various/setundef_init.ys @@ -0,0 +1,61 @@ +# Test for issue #5835: setundef -undriven should not cause conflicts +# with init attributes on undriven wires. + +# Test 1: Basic case from the bug report - undriven wire with init attribute +read_rtlil << EOT +module \top + attribute \init 3 + wire width 4 \i +end +EOT +setundef -undriven -undef +# Verify that the init attribute was removed from the undriven wire +select -assert-count 0 w:* a:init %i +# Verify that opt doesn't crash with "Conflicting init values" error +opt +design -reset + +# Test 2: setundef -undriven -zero with init attribute +read_rtlil << EOT +module \top + attribute \init 3 + wire width 4 \i +end +EOT +setundef -undriven -zero +select -assert-count 0 w:* a:init %i +opt +design -reset + +# Test 3: setundef -undriven -one with init attribute +read_rtlil << EOT +module \top + attribute \init 3 + wire width 4 \i +end +EOT +setundef -undriven -one +select -assert-count 0 w:* a:init %i +opt +design -reset + +# Test 4: Wire driven by a cell should keep its init attribute +read_rtlil << EOT +module \top + wire width 1 input 1 \clk + wire width 1 input 2 \d + attribute \init 1'0 + wire width 1 output 3 \q + cell $dff \myff + parameter \CLK_POLARITY 1'1 + parameter \WIDTH 1 + connect \CLK \clk + connect \D \d + connect \Q \q + end +end +EOT +setundef -undriven -zero +# The init attribute should still be present since the wire is driven by a FF +select -assert-count 1 w:* a:init %i +design -reset