YosysHQ / yosys

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

Spurious warnings "select out of bounds on signal" when there is no such thing ... #4363

Open smunaut opened 2 months ago

smunaut commented 2 months ago

Version

Yosys 0.40+33 (git sha1 34d9a7451, clang++ 14.0.0-1ubuntu1.1 -fPIC -Os)

On which OS did this happen?

Linux

Reproduction Steps

wget https://people.osmocom.org/tnt/stuff/ice40_spram_gen.v
yosys -p 'read_verilog ice40_spram_gen.v; synth_ice40; write_verilog x.v' -l out.log

Expected Behavior

Synthesis without warning that point to non existent problems.

Actual Behavior

The log output contains tons of

ice40_spram_gen.v:93: Warning: Range [0:-3] select out of bounds on signal `\mem_di_w': Setting 3 LSB bits to undef.
ice40_spram_gen.v:93: Warning: Range [1:-2] select out of bounds on signal `\mem_di_w': Setting 2 LSB bits to undef.
ice40_spram_gen.v:93: Warning: Range [2:-1] select out of bounds on signal `\mem_di_w': Setting 1 LSB bits to undef.
ice40_spram_gen.v:93: Warning: Range [32:29] select out of bounds on signal `\mem_di_w': Setting 1 MSB bits to undef.
ice40_spram_gen.v:93: Warning: Range [33:30] select out of bounds on signal `\mem_di_w': Setting 2 MSB bits to undef.
ice40_spram_gen.v:93: Warning: Range [34:31] select out of bounds on signal `\mem_di_w': Setting 3 MSB bits to undef.
ice40_spram_gen.v:93: Warning: Range [0:-3] select out of bounds on signal `\mem_di_w': Setting 3 LSB bits to undef.
[...]

This is line 93:

            mem_di_w[(16*x)+(4*o)+:4] =  wr_data[4*n+:4];

x and o are both positive integer so I'm not even sure how yosys would come up with [0:-3] ...

A bit later in the loop, there is access to another signal (of the same dimensions) with the same range and that one works fine.

            rd_data[4*n+:4]    = mem_do_w[(16*x)+(4*o)+:4];

Definitions:

    wire [MDW-1:0] mem_do_w;
    reg  [MDW-1:0] mem_di_w;
KrystalDelusion commented 2 months ago

I'm sure I've seen this bug before but can't find it now. If you replace x and o on line 93 with n % 2 and n / 2 respectively the warnings disappear. For some reason, using variables inside the index of a bus on the LHS of an expression are not fully evaluated until later than those on the RHS and more importantly later than the out of bounds check.

FWIW a smaller example would be:

module top (
    output reg  [31:0] rd_data,
    input  wire [31:0] wr_data
);
    // Signals
    // -------
    wire [31:0] mem_do_w;
    reg  [31:0] mem_di_w;

    // Map input data to/from 16*NW bit words
    always @(*)
    begin : map
        integer n, x, o;

        // Map actual bits
        for (n=0; n<8; n=n+1)
        begin
            // Determine position
            x = n % 2;  // Which SPRAM
            o = n / 2;  // Which nibble inside that SPRAM

            mem_di_w[(16*x)+(4*o)+:4] =  wr_data[4*n+:4];
            rd_data[4*n+:4] = mem_do_w[(16*x)+(4*o)+:4];
        end
    end
endmodule

And just calling the read_verilog command; the synth is unnecessary to get the warnings.