From a7632ab3326c5247b8152a53808413b259c13253 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 11:10:04 -0700 Subject: [PATCH] Try using an ICE40_CARRY_LUT primitive to avoid ABC issues --- techlibs/ice40/arith_map.v | 37 +++++++++++++++++++++-------------- techlibs/ice40/cells.box | 12 ++++-------- techlibs/ice40/cells_box.v | 24 ++++++++++++++--------- techlibs/ice40/cells_map.v | 24 +++++++++++++++++++++++ techlibs/ice40/cells_sim.v | 22 +++++++++++++++++++++ techlibs/ice40/ice40_opt.cc | 16 +++++++++++++-- techlibs/ice40/synth_ice40.cc | 2 +- 7 files changed, 102 insertions(+), 35 deletions(-) diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v index 4449fdc1b..eefc375dd 100644 --- a/techlibs/ice40/arith_map.v +++ b/techlibs/ice40/arith_map.v @@ -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; diff --git a/techlibs/ice40/cells.box b/techlibs/ice40/cells.box index d775efa78..34d1f372e 100644 --- a/techlibs/ice40/cells.box +++ b/techlibs/ice40/cells.box @@ -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 diff --git a/techlibs/ice40/cells_box.v b/techlibs/ice40/cells_box.v index e2a54a42c..d0eb8708c 100644 --- a/techlibs/ice40/cells_box.v +++ b/techlibs/ice40/cells_box.v @@ -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 diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v index d0ddfd02e..d4c611686 100644 --- a/techlibs/ice40/cells_map.v +++ b/techlibs/ice40/cells_map.v @@ -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 diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 322c1e5c7..b5a739a63 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -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 diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index f528607d6..edb293b93 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -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; diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 3faa10b4f..d09a1184c 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -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"); -- 2.30.2