YosysHQ / yosys

Yosys Open SYnthesis Suite
https://yosyshq.net/yosys/
ISC License
3.31k stars 861 forks source link

Misoptimization of wide shifts #4164

Open flaviens opened 5 months ago

flaviens commented 5 months ago

Version

Yosys 0.37+29 (git sha1 3c3788ee2, clang 10.0.0-4ubuntu1 -fPIC -Os)

On which OS did this happen?

Linux

Reproduction Steps

Hi there!

I stumbled into an issue where a wide shift gets some misoptimization. I could reduce it to a very simple circuit, that is packaged into this repository for helping you reproduce the issue. Interestingly, reducing the shift operand width by 1 more will clear the bug.

Please let me know if you require any more information or help, or please let me know if I did something wrong here.

Thank you! Flavien

Expected Behavior

no optimization Output: 00000000 with optimization Output: 00000000

Actual Behavior

no optimization Output: 00000000 with optimization Output: ffffffff

povik commented 5 months ago

Reproduces with

read_verilog -sv <<EOF
module top(out_data);
  wire [90:0] fullone_0;
  wire [90:0] fullone_1;
  wire [289:0] shiftout;
  output [31:0] out_data;
  wire [31:0] out_data;
  assign shiftout = fullone_0 << fullone_1;
  assign fullone_0 = '1;
  assign fullone_1 = '1;
  assign out_data[31:0] = shiftout[31:0];
endmodule
EOF
eval w:out_data
debug opt_expr
eval w:out_data

with log output

1. Executing Verilog-2005 frontend: <<EOF
Parsing SystemVerilog input from `<<EOF' to AST representation.
Generating RTLIL representation for module `\top'.
Successfully finished Verilog frontend.

2. Executing EVAL pass (evaluate the circuit given an input).
Eval result: \out_data = 0.

3. Executing OPT_EXPR pass (perform const folding).
Optimizing module top.
Replacing $shl cell `$shl$<<EOF:7$1' (B=91'1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, SHR=1) in module `top' with fixed wiring: 290'00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

4. Executing EVAL pass (evaluate the circuit given an input).
Eval result: \out_data = 32'11111111111111111111111111111111.
povik commented 5 months ago

Looks like the blame is on SigSpec::as_int overflowing here https://github.com/YosysHQ/yosys/blob/80511ced71b657e77a5389d54c6aa045c047ccaf/passes/opt/opt_expr.cc#L1306

jix commented 5 months ago

This might be the same bug as #4010. I have some work in progress to detect and error out on as_int overflows in general together with some fixes for places where it could overflow (like this optimization) but I haven't found the time finish it.