YosysHQ / yosys

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

Assertion error during 2.20.2 FSM_EXTRACT pass #1216

Open norandomtechie opened 5 years ago

norandomtechie commented 5 years ago

Steps to reproduce the issue

I have the following Verilog design meant to be mapped to the ice40HX8K FPGA:

module top (hz100, pb, ss7, ss6, ss5, ss4, ss3, ss2, ss1, ss0, left, right, red, green, blue);
  input hz100;
  input [20:0] pb;
  output [7:0] ss7;
  output [7:0] ss6;
  output [7:0] ss5;
  output [7:0] ss4;
  output [7:0] ss3;
  output [7:0] ss2;
  output [7:0] ss1;
  output [7:0] ss0;
  output [7:0] left;
  output [7:0] right;
  output red;
  output green;
  output blue;

  reg [4:0] op;
  reg [31:0] save;
  reg [31:0] entry;
  reg [31:0] nextresult;

  wire [31:0] source = displaysave ? save : entry;
  assign {left,right} = source[15:0];

  wire [4:0] key;
  wire pressed;
  scankey sk(.clk(hz100), .strobe(pressed), .out(key), .in(pb));

  always @ (posedge pressed)
      begin
        casez (key)
          5'b0????: begin
            entry <= {28'b0,key[3:0]};
          end
          5'b1????: begin
            save <= nextresult;
            op <= key;
          end

        endcase
      end

  always @(*)
    case (op)
      0: nextresult = entry;
      default: nextresult = save;
    endcase

endmodule

module scankey(clk, in, out, strobe);
    input wire clk;
    output wire [4:0] out;
    output wire       strobe;
    input  wire [20:0] in;
    wire active;
    reg [4:0] highest;

    reg [1:0] delay;
    always @(posedge clk)
      delay <= delay<<1 | active;
    assign strobe = delay[1];

    assign {active,out} = in[20] == 1 ? 6'b110100 :
                          in[19] == 1 ? 6'b110011 :
                          in[18] == 1 ? 6'b110010 :
                          in[17] == 1 ? 6'b110001 :
                          in[16] == 1 ? 6'b110000 :
                          in[15] == 1 ? 6'b101111 :
                          in[14] == 1 ? 6'b101110 :
                          in[13] == 1 ? 6'b101101 :
                          in[12] == 1 ? 6'b101100 :
                          in[11] == 1 ? 6'b101011 :
                          in[10] == 1 ? 6'b101010 :
                          in[ 9] == 1 ? 6'b101001 :
                          in[ 8] == 1 ? 6'b101000 :
                          in[ 7] == 1 ? 6'b100111 :
                          in[ 6] == 1 ? 6'b100110 :
                          in[ 5] == 1 ? 6'b100101 :
                          in[ 4] == 1 ? 6'b100100 :
                          in[ 3] == 1 ? 6'b100011 :
                          in[ 2] == 1 ? 6'b100010 :
                          in[ 1] == 1 ? 6'b100001 :
                          in[ 0] == 1 ? 6'b100000 : 6'b000000;
endmodule

This code is saved to a file named test.v, and compiled with the following command: yosys -p "synth_ice40 -top top -blif test.blif" test.v

The command was run with the latest yosys (currently at HEAD, v0.8+611).

Expected behavior

The design is supposed to compile correctly with a few warnings to produce the necessary test.blif.

Actual behavior

The following error occurs:

2.20.2. Executing FSM_EXTRACT pass (extracting FSM from design).
Extracting FSM `\op' from module `\top'.
  found $dff cell for state register: $procdff$60
  root of input selection tree: $0\op[4:0]
  found ctrl input: \key [4]
  found ctrl input: \pb [20]
  .....
  found ctrl input: \pb [0]
  found state code: 5'10000
  .....
  found state code: 5'11111
  found ctrl output: $procmux$51_CMP
  ctrl inputs: { \key [4] \pb }
  ctrl outputs: { $procmux$51_CMP $0\op[4:0] }
  transition:    5'10000 22'0--------------------- ->    5'10000 6'010000
ERROR: Assert `current_val[i].wire != NULL || current_val[i] == value.bits[i]' failed in ./kernel/consteval.h:79.
SergeyDegtyar commented 4 years ago

Checked this on Yosys 0.9+932 (git sha1 3c6a566d, gcc 8.3.0-6ubuntu1 -Og -fPIC) Now I can't reproduce this error. Maybe, It was fixed. ... 2.20.1. Executing FSM_DETECT pass (finding FSMs in design).

2.20.2. Executing FSM_EXTRACT pass (extracting FSM from design).

2.20.3. Executing FSM_OPT pass (simple optimizations of FSMs).

2.20.4. Executing OPT_CLEAN pass (remove unused cells and wires). Finding unused cells or wires in module \top.. ...

Test case: https://github.com/YosysHQ/yosys-tests/tree/master/regression/issue_01216

norandomtechie commented 4 years ago

It does work at that particular commit. Thank you!

norandomtechie commented 4 years ago

I'm afraid the error has returned with a different version of our code. The code block where this occurs has been highlighted.

// Empty top module

module top (hz100, reset, pb, ss7, ss6, ss5, ss4, ss3, ss2, ss1, ss0, left, right, red, green, blue);
  input hz100, reset;
  input [20:0] pb;
  output [7:0] ss7, ss6, ss5, ss4, ss3, ss2, ss1, ss0, left, right;
  output red, green, blue;

  reg [31:0] entry; // value being entered
  reg [31:0] saved; // saved value to use as a second operand
  reg [4:0]  op; // the selected operation
  reg        displaysaved; // show entry or saved?
  reg        equalpressed; // has equal been pressed?  
  wire [4:0] key;               // outkey of scankey module  
  wire pressed;                 // strobe of scankey module

  scankey sk(.clk(hz100), .reset(reset), .inkeys(pb), .strobe(pressed), .outkey(key));

/********************************************************************************/
// This is the mux that causes the same error
  reg [31:0] nextresult;
  always @(*) begin
    case (op)
      0: nextresult <= entry;
      19: nextresult <= saved + entry;
      18: nextresult <= saved - entry;
      default: nextresult <= saved;
    endcase
  end
/********************************************************************************/
  always @(posedge pressed, posedge reset)
  begin
    if (reset) begin
      entry <= 0;
      saved <= 0;
      op <= 0;
      displaysaved <= 0;
      equalpressed <= 0;
    end
    else if (key == 5'b10001 && displaysaved == 0) begin
      entry <= entry >> 4;
    end
    else if (key == 5'b10000) begin
      saved <= nextresult;
      displaysaved <= 1;
      equalpressed <= 1;
    end
    else if (key[4] == 0) begin
      if (equalpressed) begin
        entry <= {28'b0,key[3:0]};
        saved <= 0;
        op <= 0;
        displaysaved <= 0;
        equalpressed <= 0;
      end
      else begin
        if (entry[31:28] == 0)
          entry <= entry << 4 | key;
        displaysaved <= 0;
      end
    end
    else if (key[4] && key[1]) begin
      if (equalpressed == 0)
        saved <= nextresult;
      op <= key;
      displaysaved <= 1;
      entry <= 0;
      equalpressed <= 0;
    end
  end
  assign right = num [31:24];

  wire [31:0] num = displaysaved ? saved : entry;
  ssdec s7(.in(num[31:28]), .enable(1'b1), .out(ss7));
  ssdec s6(.in(num[27:24]), .enable(1'b1), .out(ss6));
  ssdec s5(.in(num[23:20]), .enable(1'b1), .out(ss5));
  ssdec s4(.in(num[19:16]), .enable(1'b1), .out(ss4));
  ssdec s3(.in(num[15:12]), .enable(1'b1), .out(ss3));
  ssdec s2(.in(num[11:8]),  .enable(1'b1), .out(ss2));
  ssdec s1(.in(num[7:4]),   .enable(1'b1), .out(ss1));
  ssdec s0(.in(num[3:0]),   .enable(1'b1), .out(ss0));

endmodule

// Add more modules down here...
module ssdec (in, enable, out);
  input [3:0] in;
  input enable;
  output [7:0] out;

  assign out = enable ? in == 4'hF ? 8'b01110001 :
                        in == 4'hE ? 8'b01111001 :
                        in == 4'hd ? 8'b01011110 :
                        in == 4'hC ? 8'b00111001 :
                        in == 4'hB ? 8'b01111100 :
                        in == 4'hA ? 8'b01110111 :
                        in == 4'h9 ? 8'b01101111 :
                        in == 4'h8 ? 8'b01111111 :
                        in == 4'h7 ? 8'b00000111 :
                        in == 4'h6 ? 8'b01111101 :
                        in == 4'h5 ? 8'b01101101 :
                        in == 4'h4 ? 8'b01100110 :
                        in == 4'h3 ? 8'b01001111 :
                        in == 4'h2 ? 8'b01011011 :
                        in == 4'h1 ? 8'b00000110 : 8'b00111111 : 8'b0;
endmodule
module scankey (clk, reset, inkeys, strobe, outkey);
  input clk, reset;
  input [19:0] inkeys;
  output strobe;
  output [4:0] outkey;

  reg [1:0] delay;
  always @(posedge clk, posedge reset)
  if (reset)
    delay <= 0;
  else
    delay <= delay << 1 | |inkeys;

  assign strobe = delay[1];
  assign outkey = inkeys [19] ? 5'd19 :
                  inkeys [18] ? 5'd18 :
                  inkeys [17] ? 5'd17 :
                  inkeys [16] ? 5'd16 :
                  inkeys [15] ? 5'd15 :
                  inkeys [14] ? 5'd14 :
                  inkeys [13] ? 5'd13 :
                  inkeys [12] ? 5'd12 :
                  inkeys [11] ? 5'd11 :
                  inkeys [10] ? 5'd10 :
                  inkeys [ 9] ? 5'd9  :
                  inkeys [ 8] ? 5'd8  :
                  inkeys [ 7] ? 5'd7  :
                  inkeys [ 6] ? 5'd6  :
                  inkeys [ 5] ? 5'd5  :
                  inkeys [ 4] ? 5'd4  :
                  inkeys [ 3] ? 5'd3  :
                  inkeys [ 2] ? 5'd2  :
                  inkeys [ 1] ? 5'd1  : 5'd0;
endmodule

The expected behavior is that it compiles correctly, but the actual behavior is as follows:

2.19.4. Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).
  Optimizing cells in module \top.
Performed a total of 0 changes.

2.19.5. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\top'.
Removed a total of 0 cells.

2.19.6. Executing OPT_RMDFF pass (remove dff with constant values).

2.19.7. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \top..

2.19.8. Executing OPT_EXPR pass (perform const folding).
Optimizing module top.

2.19.9. Finished OPT passes. (There is nothing left to do.)

2.20. Executing FSM pass (extract and optimize FSM).

2.20.1. Executing FSM_DETECT pass (finding FSMs in design).
Found FSM state register top.op.

2.20.2. Executing FSM_EXTRACT pass (extracting FSM from design).
  found $adff cell for state register: $procdff$160
  root of input selection tree: $0\op[4:0]
  found reset state: 5'00000 (from async reset)
  found ctrl input: $logic_and$practice.v:38$7_Y
  found ctrl input: $eq$practice.v:41$9_Y
  found ctrl input: \key [4]
  found ctrl input: \equalpressed
  found ctrl input: $logic_and$practice.v:60$14_Y
  found ctrl input: \pb [19]
  found ctrl input: \pb [18]
  found ctrl input: \pb [17]
  found ctrl input: \pb [16]
  found ctrl input: \pb [15]
  found ctrl input: \pb [14]
  found ctrl input: \pb [13]
  found ctrl input: \pb [12]
  found ctrl input: \pb [11]
  found ctrl input: \pb [10]
  found ctrl input: \pb [9]
  found ctrl input: \pb [8]
  found ctrl input: \pb [7]
  found ctrl input: \pb [6]
  found ctrl input: \pb [5]
  found ctrl input: \pb [4]
  found ctrl input: \pb [3]
  found ctrl input: \pb [2]
  found ctrl input: \pb [1]
  found state code: 5'10000
  found state code: 5'10001
  found state code: 5'10010
  found state code: 5'10011
  found state code: 5'10100
  found state code: 5'10101
  found state code: 5'10110
  found state code: 5'10111
  found state code: 5'11000
  found state code: 5'11001
  found state code: 5'11010
  found state code: 5'11011
  found state code: 5'11100
  found state code: 5'11101
  found state code: 5'11110
  found state code: 5'11111
  found ctrl output: $procmux$154_CMP
  found ctrl output: $procmux$155_CMP
  found ctrl output: $procmux$156_CMP
  ctrl inputs: { $logic_and$practice.v:60$14_Y $eq$practice.v:41$9_Y $logic_and$practice.v:38$7_Y \key [4] \equalpressed \pb [19:1] }
  ctrl outputs: { $procmux$156_CMP $procmux$155_CMP $procmux$154_CMP $0\op[4:0] }
  transition:    5'00000 24'-0000------------------- ->    5'00000 8'10000000
  transition:    5'00000 24'-0001------------------- ->    5'00000 8'10000000
  transition:    5'00000 24'0001-------------------- ->    5'00000 8'10000000
ERROR: Assert `current_val[i].wire != NULL || current_val[i] == value.bits[i]' failed in ./kernel/consteval.h:79.