diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index 47f1ed604..6b377855e 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -34,3 +34,4 @@ $(eval $(call add_share_file,share,techlibs/common/abc9_model.v)) $(eval $(call add_share_file,share,techlibs/common/abc9_map.v)) $(eval $(call add_share_file,share,techlibs/common/abc9_unmap.v)) $(eval $(call add_share_file,share,techlibs/common/cmp2lcu.v)) +$(eval $(call add_share_file,share,techlibs/common/cmp2softlogic.v)) diff --git a/techlibs/common/cmp2softlogic.v b/techlibs/common/cmp2softlogic.v new file mode 100644 index 000000000..e480b4eee --- /dev/null +++ b/techlibs/common/cmp2softlogic.v @@ -0,0 +1,117 @@ +module constgtge(C, A, B, Y); +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; + +(* force_downto *) +input [A_WIDTH-1:0] A; +(* force_downto *) +input [B_WIDTH-1:0] B; +output Y; +input C; + +wire [A_WIDTH:0] ch; +genvar n; +generate + if (B_WIDTH > A_WIDTH) begin + // Fail + end else begin + assign ch[0] = C; + for (n = 0; n < A_WIDTH; n = n + 1) begin + if (n < B_WIDTH) begin + assign ch[n + 1] = B[n] ? (ch[n] && A[n]) : (ch[n] || A[n]); + end else begin + assign ch[n + 1] = ch[n] || A[n]; + end + end + assign Y = ch[A_WIDTH]; + end +endgenerate +endmodule + +module constltle(C, A, B, Y); +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; + +(* force_downto *) +input [A_WIDTH-1:0] A; +(* force_downto *) +input [B_WIDTH-1:0] B; +output Y; +input C; + +wire [A_WIDTH:0] ch; +genvar n; +generate + if (B_WIDTH > A_WIDTH) begin + // Fail + end else begin + assign ch[0] = C; + for (n = 0; n < A_WIDTH; n = n + 1) begin + if (n < B_WIDTH) begin + assign ch[n + 1] = !B[n] ? (ch[n] && !A[n]) : (ch[n] || !A[n]); + end else begin + assign ch[n + 1] = ch[n] && !A[n]; + end + end + assign Y = ch[A_WIDTH]; + end +endgenerate +endmodule + +(* techmap_celltype = "$ge $gt $le $lt" *) +module _map_const_cmp_(A, B, Y); +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; +parameter Y_WIDTH = 0; +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; + +(* force_downto *) +input [A_WIDTH-1:0] A; +(* force_downto *) +input [B_WIDTH-1:0] B; +(* force_downto *) +output [Y_WIDTH-1:0] Y; + +parameter _TECHMAP_CELLTYPE_ = ""; + +parameter _TECHMAP_CONSTMSK_A_ = 0; +parameter _TECHMAP_CONSTVAL_A_ = 0; +parameter _TECHMAP_CONSTMSK_B_ = 0; +parameter _TECHMAP_CONSTVAL_B_ = 0; + +wire [1023:0] _TECHMAP_DO_ = "opt -fast;"; + +wire [A_WIDTH:0] ch; + +genvar n; +generate + if (Y_WIDTH != 1 || A_SIGNED || B_SIGNED) + wire _TECHMAP_FAIL_ = 1; + else if (&_TECHMAP_CONSTMSK_A_) begin + if (A_WIDTH > B_WIDTH) + wire _TECHMAP_FAIL_ = 1; + else if (_TECHMAP_CELLTYPE_ == "$lt" || _TECHMAP_CELLTYPE_ == "$le") + constgtge #(.A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH)) + _TECHMAP_REPLACE_(.A(B), .B(A), .Y(Y), + .C(_TECHMAP_CELLTYPE_ == "$lt")); + else + constltle #(.A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH)) + _TECHMAP_REPLACE_(.A(B), .B(A), .Y(Y), + .C(_TECHMAP_CELLTYPE_ == "$gt")); + end else if (&_TECHMAP_CONSTMSK_B_) begin + if (B_WIDTH > A_WIDTH) + wire _TECHMAP_FAIL_ = 1; + else if (_TECHMAP_CELLTYPE_ == "$lt" || _TECHMAP_CELLTYPE_ == "$le") + constltle #(.A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH)) + _TECHMAP_REPLACE_(.A(A), .B(B), .Y(Y), + .C(_TECHMAP_CELLTYPE_ == "$le")); + else + constgtge #(.A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH)) + _TECHMAP_REPLACE_(.A(A), .B(B), .Y(Y), + .C(_TECHMAP_CELLTYPE_ == "$ge")); + end else + wire _TECHMAP_FAIL_ = 1; +endgenerate + +endmodule diff --git a/techlibs/lattice/synth_lattice.cc b/techlibs/lattice/synth_lattice.cc index e2987d025..ba39397c4 100644 --- a/techlibs/lattice/synth_lattice.cc +++ b/techlibs/lattice/synth_lattice.cc @@ -127,6 +127,10 @@ struct SynthLatticePass : public ScriptPass log(" read/write collision\" (same result as setting the no_rw_check\n"); log(" attribute on all memories).\n"); log("\n"); + log(" -cmp2softlogic\n"); + log(" implement constant comparisons in soft logic, do not involve\n"); + log(" hard carry chains\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); @@ -135,6 +139,7 @@ struct SynthLatticePass : public ScriptPass string top_opt, edif_file, json_file, family; bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, dff, retime, abc2, abc9, iopad, nodsp, no_rw_check, have_dsp; + bool cmp2softlogic; string postfix, arith_map, brams_map, dsp_map; void clear_flags() override @@ -162,6 +167,7 @@ struct SynthLatticePass : public ScriptPass brams_map = ""; dsp_map = ""; have_dsp = false; + cmp2softlogic = false; } void execute(std::vector args, RTLIL::Design *design) override @@ -263,6 +269,10 @@ struct SynthLatticePass : public ScriptPass no_rw_check = true; continue; } + if (args[argidx] == "-cmp2softlogic") { + cmp2softlogic = true; + continue; + } break; } extra_args(args, argidx, design); @@ -343,6 +353,8 @@ struct SynthLatticePass : public ScriptPass run("peepopt"); run("opt_clean"); run("share"); + if (cmp2softlogic) + run("techmap -map +/cmp2softlogic.v"); run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4"); run("opt_expr"); run("opt_clean");