opt_clean after proc changes simulation result for explicitly-driven output bit
pending-verification
### Version
Yosys 0.64+341 (git sha1 cc9692caa, GNU /bin/c++ 11.4.0)
### On which OS did this happen?
Linux
### Reproduction Steps
opt_clean incorrectly removes cells or wires that are still live in the output cone, causing a deterministic output bit flip.
The reduced design has an explicitly-driven output out_data[0] whose value depends on a deep vector shift/mux/concat cone. After proc, the design contains multiple $dlatch and $adff cells produced from always_latch blocks where different conditions write different registers within the same block. opt_clean's unused-bit analysis appears to misjudge part of this cone as dead — likely because the liveness propagation fails to trace through chained shifts and part-selects — and removes 16 cells and 186 wires. This severs a path that ultimately feeds out_data[0], flipping it from the correct value 0 to 1 at cycle 13 under deterministic stimulus.
The bug is isolated to opt_clean alone: applying only proc produces correct simulation, while proc; opt_clean produces the mismatch. The output is fully and explicitly driven (assign out_data = {191'b0, celloutsig_0_293z[0]}), so this is not an undriven-wire comparison artifact. No Yosys warnings are emitted during the failing run.
Files in this directory:
- `top.sv`: top module
- `tb.sv`: deterministic comparison testbench
Run:
```sh
yosys -q -s yosys_script.ys
perl -pe 's/module top\\b/module top_baseline/' baseline.v > baseline_sim.v
perl -pe 's/module top\\b/module top_optimized/' optimized.v > optimized_sim.v
iverilog -g2012 -o sim.out baseline_sim.v optimized_sim.v tb.sv
vvp sim.out
```
### Expected Behavior
Expected: no deterministic 0/1 mismatch btw baseline_sim.v and optimized_sim.v.
### Actual Behavior
Observed:
```text
SIM_MISMATCH cycle=13 signal=out_data bit=0 gold=0 gate=1
```
The top module explicitly drives the whole output:
```systemverilog
assign out_data = {191'b0, celloutsig_0_293z[0]};
```
The run without the optimization pass produces no mismatch. Adding only `opt_clean` changes `out_data[0]` from `0` to `1` at cycle 13. The `opt_clean` run reports no Yosys warnings, so this is not an undriven output comparison artifact.
The relevant output cone is a vector mux/concat/part-select cone:
```systemverilog
assign celloutsig_0_293z =
celloutsig_0_24z[1] ? celloutsig_0_17z[17:5]
: { celloutsig_0_70z[6:2], celloutsig_0_194z };
assign celloutsig_0_194z = celloutsig_0_17z[20:13] <<< celloutsig_0_115z[15:8];
```
`proc` also creates several `$adff` registers and `$dlatch` cells from the reduced sequential logic. In the RTLIL dump, `opt_clean` removes 16 cells and 186 wires. Since `celloutsig_0_293z[0]` remains directly connected to `out_data[0]`, the likely failure mode is that `opt_clean`'s liveness/unused-bit analysis is treating part of this vector cone as unused even though it still contributes to the observed output bit.
## Verification Performed
Using `top.sv`:
- `proc` only: no mismatch
- `proc; opt_clean; flatten; check`: mismatch at `out_data[0]`
- `proc; opt_expr -full; opt_clean; flatten; check`: same mismatch
- `proc; opt; flatten; check`: same mismatch
[opt-clean.zip](https://github.com/user-attachments/files/28700998/opt-clean.zip)
1 条评论