Try using an ICE40_CARRY_LUT primitive to avoid ABC issues
authorEddie Hung <eddie@fpgeh.com>
Wed, 17 Apr 2019 18:10:04 +0000 (11:10 -0700)
committerEddie Hung <eddie@fpgeh.com>
Wed, 17 Apr 2019 18:10:04 +0000 (11:10 -0700)
techlibs/ice40/arith_map.v
techlibs/ice40/cells.box
techlibs/ice40/cells_box.v
techlibs/ice40/cells_map.v
techlibs/ice40/cells_sim.v
techlibs/ice40/ice40_opt.cc
techlibs/ice40/synth_ice40.cc

index 4449fdc1bf9961acce2d4f40dc204ee919e68165..eefc375dd16f417d5ca556ca8cfb0b05e3fb6f2d 100644 (file)
@@ -44,25 +44,32 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO);
 
        genvar i;
        generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
-               SB_CARRY carry (
-                       .I0(AA[i]),
-                       .I1(BB[i]),
-                       .CI(C[i]),
-                       .CO(CO[i])
-               );
-               SB_LUT4 #(
-                       //         I0: 1010 1010 1010 1010
-                       //         I1: 1100 1100 1100 1100
-                       //         I2: 1111 0000 1111 0000
-                       //         I3: 1111 1111 0000 0000
-                       .LUT_INIT(16'b 0110_1001_1001_0110)
-               ) adder (
-                       .I0(1'b0),
+               ICE40_CARRY_LUT carry_lut (
                        .I1(AA[i]),
                        .I2(BB[i]),
-                       .I3(C[i]),
+                       .CI(C[i]),
+                       .CO(CO[i]),
                        .O(Y[i])
                );
+//             SB_CARRY carry (
+//                     .I0(AA[i]),
+//                     .I1(BB[i]),
+//                     .CI(C[i]),
+//                     .CO(CO[i])
+//             );
+//             SB_LUT4 #(
+//                     //         I0: 1010 1010 1010 1010
+//                     //         I1: 1100 1100 1100 1100
+//                     //         I2: 1111 0000 1111 0000
+//                     //         I3: 1111 1111 0000 0000
+//                     .LUT_INIT(16'b 0110_1001_1001_0110)
+//             ) adder (
+//                     .I0(1'b0),
+//                     .I1(AA[i]),
+//                     .I2(BB[i]),
+//                     .I3(C[i]),
+//                     .O(Y[i])
+//             );
        end endgenerate
 
        assign X = AA ^ BB;
index d775efa78ce1229fd1c10c67730ce59602b7d88a..34d1f372ef3e2ffdd2593c9b638d3cf0b23214f7 100644 (file)
@@ -2,12 +2,8 @@
 
 # NB: Inputs/Outputs must be ordered alphabetically
 
-# Inputs: CI I0 I1
-# Outputs: CO
-SB_CARRY 1 1 3 1
+# Inputs: CI I1 I2
+# Outputs: CO O
+ICE40_CARRY_LUT 1 1 3 2
 126 259 231
-
-# Inputs: I0 I1 I2 I3
-# Outputs: O
-SB_LUT4 2 1 4 1
-316 379 400 449
+316 400 379
index e2a54a42ca46457daf5df5325f6686219b5cdd4a..d0eb8708c22191bd8dc5f21780d532dde6236e5e 100644 (file)
@@ -1,12 +1,18 @@
 (* abc_box_id = 1 *)
-module SB_CARRY (output CO, input CI, I0, I1);
-       assign CO = (I0 && I1) || ((I0 || I1) && CI);
-endmodule
+module ICE40_CARRY_LUT (output CO, O, input CI, I1, I2);
+       assign CO = (I1 && I2) || ((I1 || I2) && CI);
 
-(* abc_box_id = 2 *)
-module SB_LUT4 (output O, input I0, I1, I2, I3);
-       parameter [15:0] LUT_INIT = 0;
-       // Indicate this is a black-box
-       assign O = 1'b0;
-endmodule
+       wire I0, I3;
+       assign I0 = 1'b0;
+       assign I3 = CI;
 
+       //                            I0: 1010 1010 1010 1010
+       //                            I1: 1100 1100 1100 1100
+       //                            I2: 1111 0000 1111 0000
+       //                            I3: 1111 1111 0000 0000
+       localparam [15:0] LUT_INIT = 16'b 0110_1001_1001_0110;
+       wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
+       wire [3:0] s2 = I2 ?       s3[ 7:4] :       s3[3:0];
+       wire [1:0] s1 = I1 ?       s2[ 3:2] :       s2[1:0];
+       assign O = I0 ? s1[1] : s1[0];
+endmodule
index d0ddfd02e0b1c223312f1ee015ea62430f8cb71a..d4c61168640285ac7360c2cad5c836f275aec477 100644 (file)
@@ -57,3 +57,27 @@ module \$lut (A, Y);
   endgenerate
 endmodule
 `endif
+
+`ifndef NO_CARRY
+module ICE40_CARRY_LUT (output CO, O, input CI, I1, I2);
+       SB_CARRY carry (
+               .I0(I1),
+               .I1(I2),
+               .CI(CI),
+               .CO(CO),
+       );
+       SB_LUT4 #(
+               //         I0: 1010 1010 1010 1010
+               //         I1: 1100 1100 1100 1100
+               //         I2: 1111 0000 1111 0000
+               //         I3: 1111 1111 0000 0000
+               .LUT_INIT(16'b 0110_1001_1001_0110)
+       ) adder (
+               .I0(1'b0),
+               .I1(I1),
+               .I2(I2),
+               .I3(CI),
+               .O(O)
+       );
+endmodule
+`endif
index 322c1e5c7da5c158b533bf1a4f2aa1f743d5d1c4..b5a739a63b101631057e180c1065154767f7f389 100644 (file)
@@ -1384,3 +1384,25 @@ module SB_MAC16 (
        assign LCI = (BOTADDSUB_CARRYSELECT == 0) ? 1'b0 : (BOTADDSUB_CARRYSELECT == 1) ? 1'b1 : (BOTADDSUB_CARRYSELECT == 2) ? ACCUMCI : CI;
        assign O = {Oh, Ol};
 endmodule
+
+module ICE40_CARRY_LUT (input CI, input I1, input I2, output CO, output O);
+       SB_CARRY carry (
+               .I0(I1),
+               .I1(I2),
+               .CI(CI),
+               .CO(CO),
+       );
+       SB_LUT4 #(
+               //         I0: 1010 1010 1010 1010
+               //         I1: 1100 1100 1100 1100
+               //         I2: 1111 0000 1111 0000
+               //         I3: 1111 1111 0000 0000
+               .LUT_INIT(16'b 0110_1001_1001_0110)
+       ) adder (
+               .I0(1'b0),
+               .I1(I1),
+               .I2(I2),
+               .I3(CI),
+               .O(O)
+       );
+endmodule
index f528607d6dabaa5962d9c3db807ed3fe213947c4..edb293b93ba4753c4b6cf6632c082eb3d5dbd3a9 100644 (file)
@@ -47,16 +47,20 @@ static void run_ice40_opts(Module *module)
                        continue;
                }
 
-               if (cell->type == "\\SB_CARRY")
+               if (cell->type.in("\\SB_CARRY", "\\ICE40_CARRY_LUT"))
                {
                        SigSpec non_const_inputs, replacement_output;
                        int count_zeros = 0, count_ones = 0;
 
                        SigBit inbit[3] = {
-                               get_bit_or_zero(cell->getPort("\\I0")),
                                get_bit_or_zero(cell->getPort("\\I1")),
                                get_bit_or_zero(cell->getPort("\\CI"))
                        };
+                       if (cell->type == "\\SB_CARRY")
+                               inbit[2] = get_bit_or_zero(cell->getPort("\\I0"));
+                       else if (cell->type == "\\ICE40_CARRY_LUT")
+                               inbit[2] = get_bit_or_zero(cell->getPort("\\I2"));
+                       else log_abort();
                        for (int i = 0; i < 3; i++)
                                if (inbit[i].wire == nullptr) {
                                        if (inbit[i] == State::S1)
@@ -79,6 +83,14 @@ static void run_ice40_opts(Module *module)
                                module->design->scratchpad_set_bool("opt.did_something", true);
                                log("Optimized away SB_CARRY cell %s.%s: CO=%s\n",
                                                log_id(module), log_id(cell), log_signal(replacement_output));
+
+                               if (cell->type == "\\ICE40_CARRY_LUT")
+                                       module->addLut(NEW_ID,
+                                               { RTLIL::S0, cell->getPort("\\I1"), cell->getPort("\\I2"), cell->getPort("\\CI") },
+                                               cell->getPort("\\O"),
+                                               RTLIL::Const("0110_1001_1001_0110"),
+                                               cell->get_src_attribute());
+
                                module->remove(cell);
                        }
                        continue;
index 3faa10b4f90560b49e7724414a4c29ff0ce95854..d09a1184ccdd64dc412014e7b8b12017019d7b75 100644 (file)
@@ -296,7 +296,7 @@ struct SynthIce40Pass : public ScriptPass
                                run("opt_merge");
                                run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
                        }
-                       run("techmap -D NO_LUT -map +/ice40/cells_map.v");
+                       run("techmap -D NO_LUT -D NO_CARRY -map +/ice40/cells_map.v");
                        run("opt_expr -mux_undef");
                        run("simplemap");
                        run("ice40_ffinit");