mirror of https://github.com/YosysHQ/yosys.git
setundef: strip init attributes from undriven wires (fixes #5835)
When `setundef -undriven` connects an undriven wire to a replacement value, the wire's \\init attribute (if present) is now removed. Previously, the init attribute was left intact, causing downstream passes like opt_merge to report "Conflicting init values" errors because the init value contradicted the newly assigned constant. For wires that are entirely undriven, the init attribute is removed completely. For partially undriven wires (where only some bits are undriven), only the corresponding init bits are cleared to x. Wires driven by flip-flops or other cells are not affected, as they are excluded from the undriven signal set before this code runs.
This commit is contained in:
parent
e56c6a954c
commit
46f9f887f7
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Reference in New Issue