From fffe42d4c1dbfdf976ecb84e16a759552c8e2dd0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 17 Jan 2020 10:21:22 -0800 Subject: cmp2lut: comment out unused since 362f4f9 --- techlibs/common/cmp2lut.v | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'techlibs') diff --git a/techlibs/common/cmp2lut.v b/techlibs/common/cmp2lut.v index 1c8192b85..2f1bfd901 100644 --- a/techlibs/common/cmp2lut.v +++ b/techlibs/common/cmp2lut.v @@ -57,10 +57,10 @@ function automatic [(1 << `LUT_WIDTH)-1:0] gen_lut; o_bit = (lhs > rhs); if (operation == 3) o_bit = (lhs >= rhs); - if (operation == 4) - o_bit = (lhs == rhs); - if (operation == 5) - o_bit = (lhs != rhs); +// if (operation == 4) +// o_bit = (lhs == rhs); +// if (operation == 5) +// o_bit = (lhs != rhs); gen_lut = gen_lut | (o_bit << n); end end @@ -75,10 +75,10 @@ generate localparam operation = 2; if (_TECHMAP_CELLTYPE_ == "$ge") localparam operation = 3; - if (_TECHMAP_CELLTYPE_ == "$eq") - localparam operation = 4; - if (_TECHMAP_CELLTYPE_ == "$ne") - localparam operation = 5; +// if (_TECHMAP_CELLTYPE_ == "$eq") +// localparam operation = 4; +// if (_TECHMAP_CELLTYPE_ == "$ne") +// localparam operation = 5; if (A_WIDTH > `LUT_WIDTH || B_WIDTH > `LUT_WIDTH || Y_WIDTH != 1) wire _TECHMAP_FAIL_ = 1; -- cgit v1.2.3 From 9b6370067858aa37825e7a030cd204726f0b58f9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 17 Jan 2020 10:51:27 -0800 Subject: techmap +/cmp2lcu.v for decomposing arithmetic compares to $lcu --- techlibs/common/Makefile.inc | 1 + techlibs/common/cmp2lcu.v | 83 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 techlibs/common/cmp2lcu.v (limited to 'techlibs') diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index d5e69a241..7b1e4b430 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -30,3 +30,4 @@ $(eval $(call add_share_file,share,techlibs/common/cmp2lut.v)) $(eval $(call add_share_file,share,techlibs/common/cells.lib)) $(eval $(call add_share_file,share,techlibs/common/mul2dsp.v)) $(eval $(call add_share_file,share,techlibs/common/abc9_model.v)) +$(eval $(call add_share_file,share,techlibs/common/cmp2lcu.v)) diff --git a/techlibs/common/cmp2lcu.v b/techlibs/common/cmp2lcu.v new file mode 100644 index 000000000..433f88fae --- /dev/null +++ b/techlibs/common/cmp2lcu.v @@ -0,0 +1,83 @@ +// This pass performs an optimisation that decomposes wide arithmetic +// comparisons into LUT-size chunks (as guided by the `LUT_WIDTH +// macro) connected to a single lookahead-carry-unit $lcu cell, +// which is typically mapped to dedicated (and fast) FPGA +// carry-chains. +(* techmap_celltype = "$lt $le $gt $ge" *) +module _90_lcu_cmp_ (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; +parameter Y_WIDTH = 0; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +parameter _TECHMAP_CELLTYPE_ = ""; +localparam gt_width = `LUT_WIDTH/2; + +generate + if (_TECHMAP_CELLTYPE_ == "" || (A_WIDTH <= gt_width || B_WIDTH <= gt_width)) + wire _TECHMAP_FAIL_ = 1; + else if (_TECHMAP_CELLTYPE_ == "$lt") begin + // Transform $lt into $gt by swapping A and B + $gt #(.A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(B), .B(A), .Y(Y)); + end + else if (_TECHMAP_CELLTYPE_ == "$le") begin + // Transform $le into $ge by swapping A and B + $ge #(.A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(B), .B(A), .Y(Y)); + end + else begin + // Perform sign extension on A and B + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; + wire [WIDTH-1:0] AA = {{(WIDTH-A_WIDTH){A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A}; + wire [WIDTH-1:0] BB = {{(WIDTH-B_WIDTH){B_SIGNED ? B[B_WIDTH-1] : 1'b0}}, B}; + + // Compute width of $lcu/carry-chain cell + localparam lcu_width = (WIDTH+gt_width-1)/gt_width; + wire [lcu_width-1:0] P, G, CO; + genvar i, j; + integer j; + for (i = 0; i < WIDTH; i=i+gt_width) begin + wire [gt_width-1:0] PP, GG; + if (i < WIDTH-gt_width) begin + // Bit-wise equality (xnor) of sign-extended A and B + assign PP = AA[i +: gt_width] ^~ BB[i +: gt_width]; + // Priority "encoder" that checks A[i] == 1'b1 && B[i] == 1'b0 + // from MSB down, deferring to less significant bits if the + // MSBs are equal + assign GG[gt_width-1] = AA[i+gt_width-1] & ~BB[i+gt_width-1]; + for (j = gt_width-2; j >= 0; j=j-1) + assign GG[j] = &PP[gt_width-1:j+1] & (AA[i+j] & ~BB[i+j]); + // Propagate only if all bits are equal + // (inconclusive evidence to say A >= B) + assign P[i/gt_width] = &PP; + // Generate if any pairs call for it + assign G[i/gt_width] = |GG; + end + else begin + assign PP = AA[WIDTH-1:i] ^~ BB[WIDTH-1:i]; + if (A_SIGNED && B_SIGNED) + assign GG[WIDTH-i-1] = ~AA[WIDTH-1] & BB[WIDTH-1]; + else + assign GG[WIDTH-i-1] = AA[WIDTH-1] & ~BB[WIDTH-1]; + for (j = WIDTH-i-2; j >= 0; j=j-1) + assign GG[j] = &PP[WIDTH-i-1:j+1] & (AA[i+j] & ~BB[i+j]); + assign P[i/gt_width] = &PP[WIDTH-i-1:0]; + assign G[i/gt_width] = |GG[WIDTH-i-1:0]; + end + end + // For $ge operation, start with the assumption that A and B are + // equal (propagating this equality if A and B turn out to be so) + if (_TECHMAP_CELLTYPE_ == "$ge") + wire CI = 1'b1; + else + wire CI = 1'b0; + $lcu #(.WIDTH(lcu_width)) lcu (.P(P), .G(G), .CI(CI), .CO(CO)); + assign Y = CO[lcu_width-1]; + end +endgenerate +endmodule -- cgit v1.2.3 From da880d5016c10ed966235fabf506467a293fc3a1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 20 Jan 2020 12:52:47 -0800 Subject: Cleanup cmp2lcu.v --- techlibs/common/cmp2lcu.v | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'techlibs') diff --git a/techlibs/common/cmp2lcu.v b/techlibs/common/cmp2lcu.v index 433f88fae..60e03bde2 100644 --- a/techlibs/common/cmp2lcu.v +++ b/techlibs/common/cmp2lcu.v @@ -17,18 +17,18 @@ input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; parameter _TECHMAP_CELLTYPE_ = ""; -localparam gt_width = `LUT_WIDTH/2; +localparam cmp_width = `LUT_WIDTH/2; generate - if (_TECHMAP_CELLTYPE_ == "" || (A_WIDTH <= gt_width || B_WIDTH <= gt_width)) + if (_TECHMAP_CELLTYPE_ == "" || (A_WIDTH <= cmp_width || B_WIDTH <= cmp_width)) wire _TECHMAP_FAIL_ = 1; else if (_TECHMAP_CELLTYPE_ == "$lt") begin // Transform $lt into $gt by swapping A and B - $gt #(.A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(B), .B(A), .Y(Y)); + $gt #(.A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(B), .B(A), .Y(Y)); end else if (_TECHMAP_CELLTYPE_ == "$le") begin // Transform $le into $ge by swapping A and B - $ge #(.A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(B), .B(A), .Y(Y)); + $ge #(.A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(B), .B(A), .Y(Y)); end else begin // Perform sign extension on A and B @@ -37,26 +37,26 @@ generate wire [WIDTH-1:0] BB = {{(WIDTH-B_WIDTH){B_SIGNED ? B[B_WIDTH-1] : 1'b0}}, B}; // Compute width of $lcu/carry-chain cell - localparam lcu_width = (WIDTH+gt_width-1)/gt_width; + localparam lcu_width = (WIDTH+cmp_width-1)/cmp_width; wire [lcu_width-1:0] P, G, CO; genvar i, j; integer j; - for (i = 0; i < WIDTH; i=i+gt_width) begin - wire [gt_width-1:0] PP, GG; - if (i < WIDTH-gt_width) begin + for (i = 0; i < WIDTH; i=i+cmp_width) begin + wire [cmp_width-1:0] PP, GG; + if (i < WIDTH-cmp_width) begin // Bit-wise equality (xnor) of sign-extended A and B - assign PP = AA[i +: gt_width] ^~ BB[i +: gt_width]; + assign PP = AA[i +: cmp_width] ^~ BB[i +: cmp_width]; // Priority "encoder" that checks A[i] == 1'b1 && B[i] == 1'b0 // from MSB down, deferring to less significant bits if the // MSBs are equal - assign GG[gt_width-1] = AA[i+gt_width-1] & ~BB[i+gt_width-1]; - for (j = gt_width-2; j >= 0; j=j-1) - assign GG[j] = &PP[gt_width-1:j+1] & (AA[i+j] & ~BB[i+j]); + assign GG[cmp_width-1] = AA[i+cmp_width-1] & ~BB[i+cmp_width-1]; + for (j = cmp_width-2; j >= 0; j=j-1) + assign GG[j] = &PP[cmp_width-1:j+1] & (AA[i+j] & ~BB[i+j]); // Propagate only if all bits are equal // (inconclusive evidence to say A >= B) - assign P[i/gt_width] = &PP; + assign P[i/cmp_width] = &PP; // Generate if any pairs call for it - assign G[i/gt_width] = |GG; + assign G[i/cmp_width] = |GG; end else begin assign PP = AA[WIDTH-1:i] ^~ BB[WIDTH-1:i]; @@ -66,8 +66,8 @@ generate assign GG[WIDTH-i-1] = AA[WIDTH-1] & ~BB[WIDTH-1]; for (j = WIDTH-i-2; j >= 0; j=j-1) assign GG[j] = &PP[WIDTH-i-1:j+1] & (AA[i+j] & ~BB[i+j]); - assign P[i/gt_width] = &PP[WIDTH-i-1:0]; - assign G[i/gt_width] = |GG[WIDTH-i-1:0]; + assign P[i/cmp_width] = &PP[WIDTH-i-1:0]; + assign G[i/cmp_width] = |GG[WIDTH-i-1:0]; end end // For $ge operation, start with the assumption that A and B are -- cgit v1.2.3 From 8e851badc49a4412a1e4a5f6881ef72647213bd9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 20 Jan 2020 15:06:50 -0800 Subject: Cleanup --- techlibs/common/cmp2lcu.v | 59 ++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) (limited to 'techlibs') diff --git a/techlibs/common/cmp2lcu.v b/techlibs/common/cmp2lcu.v index 60e03bde2..d427a4cd3 100644 --- a/techlibs/common/cmp2lcu.v +++ b/techlibs/common/cmp2lcu.v @@ -17,10 +17,9 @@ input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; parameter _TECHMAP_CELLTYPE_ = ""; -localparam cmp_width = `LUT_WIDTH/2; generate - if (_TECHMAP_CELLTYPE_ == "" || (A_WIDTH <= cmp_width || B_WIDTH <= cmp_width)) + if (_TECHMAP_CELLTYPE_ == "") wire _TECHMAP_FAIL_ = 1; else if (_TECHMAP_CELLTYPE_ == "$lt") begin // Transform $lt into $gt by swapping A and B @@ -30,45 +29,43 @@ generate // Transform $le into $ge by swapping A and B $ge #(.A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(B), .B(A), .Y(Y)); end - else begin + else if (A_WIDTH != B_WIDTH) begin // Perform sign extension on A and B localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; wire [WIDTH-1:0] AA = {{(WIDTH-A_WIDTH){A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A}; wire [WIDTH-1:0] BB = {{(WIDTH-B_WIDTH){B_SIGNED ? B[B_WIDTH-1] : 1'b0}}, B}; - - // Compute width of $lcu/carry-chain cell - localparam lcu_width = (WIDTH+cmp_width-1)/cmp_width; + if (_TECHMAP_CELLTYPE_ == "$gt") + $gt #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(WIDTH), .B_WIDTH(WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(AA), .B(BB), .Y(Y)); + else if (_TECHMAP_CELLTYPE_ == "$ge") + $ge #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(WIDTH), .B_WIDTH(WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(AA), .B(BB), .Y(Y)); + else + wire _TECHMAP_FAIL_ = 1; + end + else begin + localparam cmp_width = `LUT_WIDTH/2; + localparam lcu_width = (A_WIDTH+cmp_width-1)/cmp_width; wire [lcu_width-1:0] P, G, CO; genvar i, j; - integer j; - for (i = 0; i < WIDTH; i=i+cmp_width) begin + for (i = 0; i < A_WIDTH; i=i+cmp_width) begin wire [cmp_width-1:0] PP, GG; - if (i < WIDTH-cmp_width) begin + for (j = cmp_width-1; j >= 0 && i+j < A_WIDTH; j = j-1) begin // Bit-wise equality (xnor) of sign-extended A and B - assign PP = AA[i +: cmp_width] ^~ BB[i +: cmp_width]; - // Priority "encoder" that checks A[i] == 1'b1 && B[i] == 1'b0 - // from MSB down, deferring to less significant bits if the - // MSBs are equal - assign GG[cmp_width-1] = AA[i+cmp_width-1] & ~BB[i+cmp_width-1]; - for (j = cmp_width-2; j >= 0; j=j-1) - assign GG[j] = &PP[cmp_width-1:j+1] & (AA[i+j] & ~BB[i+j]); - // Propagate only if all bits are equal - // (inconclusive evidence to say A >= B) - assign P[i/cmp_width] = &PP; - // Generate if any pairs call for it - assign G[i/cmp_width] = |GG; - end - else begin - assign PP = AA[WIDTH-1:i] ^~ BB[WIDTH-1:i]; - if (A_SIGNED && B_SIGNED) - assign GG[WIDTH-i-1] = ~AA[WIDTH-1] & BB[WIDTH-1]; + assign PP[j] = A[i+j] ^~ B[i+j]; + if (i+j == A_WIDTH-1 && A_SIGNED && B_SIGNED) + assign GG[j] = ~A[i+j] & B[i+j]; + else if (j == cmp_width-1) + assign GG[j] = A[i+j] & ~B[i+j]; else - assign GG[WIDTH-i-1] = AA[WIDTH-1] & ~BB[WIDTH-1]; - for (j = WIDTH-i-2; j >= 0; j=j-1) - assign GG[j] = &PP[WIDTH-i-1:j+1] & (AA[i+j] & ~BB[i+j]); - assign P[i/cmp_width] = &PP[WIDTH-i-1:0]; - assign G[i/cmp_width] = |GG[WIDTH-i-1:0]; + // Priority "encoder" that checks A[i] == 1'b1 && B[i] == 1'b0 + // from MSB down, deferring to less significant bits if the + // MSBs are equal + assign GG[j] = &PP[cmp_width-1:j+1] & (A[i+j] & ~B[i+j]); end + // Propagate only if all bit pairs are equal + // (inconclusive evidence to say A >= B) + assign P[i/cmp_width] = &PP; + // Generate if any bit pairs call for it + assign G[i/cmp_width] = |GG; end // For $ge operation, start with the assumption that A and B are // equal (propagating this equality if A and B turn out to be so) -- cgit v1.2.3 From f68d723cdccdb1a604077e2a3526de2a5198123c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 20 Jan 2020 16:42:08 -0800 Subject: Refactor +/cmp2lcu.v into recursive techmap --- techlibs/common/cmp2lcu.v | 103 +++++++++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 38 deletions(-) (limited to 'techlibs') diff --git a/techlibs/common/cmp2lcu.v b/techlibs/common/cmp2lcu.v index d427a4cd3..524bd4437 100644 --- a/techlibs/common/cmp2lcu.v +++ b/techlibs/common/cmp2lcu.v @@ -29,52 +29,79 @@ generate // Transform $le into $ge by swapping A and B $ge #(.A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(B), .B(A), .Y(Y)); end - else if (A_WIDTH != B_WIDTH) begin + else begin // Perform sign extension on A and B localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; wire [WIDTH-1:0] AA = {{(WIDTH-A_WIDTH){A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A}; wire [WIDTH-1:0] BB = {{(WIDTH-B_WIDTH){B_SIGNED ? B[B_WIDTH-1] : 1'b0}}, B}; - if (_TECHMAP_CELLTYPE_ == "$gt") - $gt #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(WIDTH), .B_WIDTH(WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(AA), .B(BB), .Y(Y)); - else if (_TECHMAP_CELLTYPE_ == "$ge") - $ge #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(WIDTH), .B_WIDTH(WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(AA), .B(BB), .Y(Y)); - else - wire _TECHMAP_FAIL_ = 1; - end - else begin - localparam cmp_width = `LUT_WIDTH/2; - localparam lcu_width = (A_WIDTH+cmp_width-1)/cmp_width; - wire [lcu_width-1:0] P, G, CO; - genvar i, j; - for (i = 0; i < A_WIDTH; i=i+cmp_width) begin - wire [cmp_width-1:0] PP, GG; - for (j = cmp_width-1; j >= 0 && i+j < A_WIDTH; j = j-1) begin - // Bit-wise equality (xnor) of sign-extended A and B - assign PP[j] = A[i+j] ^~ B[i+j]; - if (i+j == A_WIDTH-1 && A_SIGNED && B_SIGNED) - assign GG[j] = ~A[i+j] & B[i+j]; - else if (j == cmp_width-1) - assign GG[j] = A[i+j] & ~B[i+j]; - else - // Priority "encoder" that checks A[i] == 1'b1 && B[i] == 1'b0 - // from MSB down, deferring to less significant bits if the - // MSBs are equal - assign GG[j] = &PP[cmp_width-1:j+1] & (A[i+j] & ~B[i+j]); - end - // Propagate only if all bit pairs are equal - // (inconclusive evidence to say A >= B) - assign P[i/cmp_width] = &PP; - // Generate if any bit pairs call for it - assign G[i/cmp_width] = |GG; - end // For $ge operation, start with the assumption that A and B are // equal (propagating this equality if A and B turn out to be so) if (_TECHMAP_CELLTYPE_ == "$ge") - wire CI = 1'b1; + localparam CI = 1'b1; else - wire CI = 1'b0; - $lcu #(.WIDTH(lcu_width)) lcu (.P(P), .G(G), .CI(CI), .CO(CO)); - assign Y = CO[lcu_width-1]; + localparam CI = 1'b0; + $__CMP2LCU #(.AB_WIDTH(WIDTH), .AB_SIGNED(A_SIGNED && B_SIGNED), .LCU_WIDTH(0), .BUDGET(`LUT_WIDTH), .CI(CI)) + _TECHMAP_REPLACE_ (.A(AA), .B(BB), .P(), .G(), .PP(1'b1), .GG(1'b0), .Y(Y)); + end +endgenerate +endmodule + +module $__CMP2LCU (A, B, P, G, PP, GG, Y); + +parameter AB_WIDTH = 0; +parameter AB_SIGNED = 0; +parameter LCU_WIDTH = 0; +parameter BUDGET = 0; +parameter CI = 0; + +input [AB_WIDTH-1:0] A; +input [AB_WIDTH-1:0] B; +input [LCU_WIDTH-1:0] P; +input [LCU_WIDTH-1:0] G; +input PP; +input GG; +output Y; + +parameter [AB_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0; +parameter [AB_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; + +generate + if (AB_WIDTH == 0) begin + if (BUDGET < `LUT_WIDTH) + $__CMP2LCU #(.AB_WIDTH(AB_WIDTH), .AB_SIGNED(AB_SIGNED), .LCU_WIDTH(LCU_WIDTH+1), .BUDGET(`LUT_WIDTH), .CI(CI)) + _TECHMAP_REPLACE_ (.A(A), .B(B), .P({P, PP}), .G({G, GG}), .PP(1'b1), .GG(1'b0), .Y(Y)); + else begin + wire [LCU_WIDTH-1:0] CO; + $lcu #(.WIDTH(LCU_WIDTH)) _TECHMAP_REPLACE_ (.P(P), .G(G), .CI(CI), .CO(CO)); + assign Y = CO[LCU_WIDTH-1]; + end + end + else begin + if (BUDGET < 2) + $__CMP2LCU #(.AB_WIDTH(AB_WIDTH), .AB_SIGNED(AB_SIGNED), .LCU_WIDTH(LCU_WIDTH+1), .BUDGET(`LUT_WIDTH), .CI(CI)) + _TECHMAP_REPLACE_ (.A(A), .B(B), .P({P, PP}), .G({G, GG}), .PP(1'b1), .GG(1'b0), .Y(Y)); + else begin + wire PPP, GGG; + // Bit-wise equality (xnor) of A and B + assign PPP = A[AB_WIDTH-1] ^~ B[AB_WIDTH-1]; + if (AB_SIGNED) + assign GGG = ~A[AB_WIDTH-1] & B[AB_WIDTH-1]; + else if (BUDGET == `LUT_WIDTH) + assign GGG = A[AB_WIDTH-1] & ~B[AB_WIDTH-1]; + else + // Priority "encoder" that checks A[i] == 1'b1 && B[i] == 1'b0 + // from MSB down, deferring to less significant bits if the + // MSBs are equal + assign GGG = PP & (A[AB_WIDTH-1] & ~B[AB_WIDTH-1]); + $__CMP2LCU #(.AB_WIDTH(AB_WIDTH-1), .AB_SIGNED(1'b0), .LCU_WIDTH(LCU_WIDTH), .BUDGET(BUDGET-2), .CI(CI)) + _TECHMAP_REPLACE_ (.A(A[AB_WIDTH-2:0]), .B(B[AB_WIDTH-2:0]), .P(P), .G(G), + // Propagate only if all bit pairs are equal + // (inconclusive evidence to say A >= B) + .PP(PP & PPP), + // Generate if any bit pairs call for it + .GG(GG | GGG), + .Y(Y)); + end end endgenerate endmodule -- cgit v1.2.3 From 99a32432aa47833850cd3bed37bed926e16d9a76 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 20 Jan 2020 17:00:35 -0800 Subject: +/cmp2lcu.v to work efficiently for fully/partially constant inputs --- techlibs/common/cmp2lcu.v | 75 ++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 33 deletions(-) (limited to 'techlibs') diff --git a/techlibs/common/cmp2lcu.v b/techlibs/common/cmp2lcu.v index 524bd4437..b302d592f 100644 --- a/techlibs/common/cmp2lcu.v +++ b/techlibs/common/cmp2lcu.v @@ -40,67 +40,76 @@ generate localparam CI = 1'b1; else localparam CI = 1'b0; - $__CMP2LCU #(.AB_WIDTH(WIDTH), .AB_SIGNED(A_SIGNED && B_SIGNED), .LCU_WIDTH(0), .BUDGET(`LUT_WIDTH), .CI(CI)) - _TECHMAP_REPLACE_ (.A(AA), .B(BB), .P(), .G(), .PP(1'b1), .GG(1'b0), .Y(Y)); + $__CMP2LCU #(.AB_WIDTH(WIDTH), .AB_SIGNED(A_SIGNED && B_SIGNED), .LCU_WIDTH(1), .BUDGET(`LUT_WIDTH), .CI(CI)) + _TECHMAP_REPLACE_ (.A(AA), .B(BB), .P(1'b1), .G(1'b0), .Y(Y)); end endgenerate endmodule -module $__CMP2LCU (A, B, P, G, PP, GG, Y); +module $__CMP2LCU (A, B, P, G, Y); parameter AB_WIDTH = 0; parameter AB_SIGNED = 0; -parameter LCU_WIDTH = 0; +parameter LCU_WIDTH = 1; parameter BUDGET = 0; parameter CI = 0; -input [AB_WIDTH-1:0] A; -input [AB_WIDTH-1:0] B; -input [LCU_WIDTH-1:0] P; -input [LCU_WIDTH-1:0] G; -input PP; -input GG; +input [AB_WIDTH-1:0] A; // A from original $gt/$ge +input [AB_WIDTH-1:0] B; // B from original $gt/$ge +input [LCU_WIDTH-1:0] P; // P of $lcu +input [LCU_WIDTH-1:0] G; // G of $lcu output Y; parameter [AB_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0; parameter [AB_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; +parameter [LCU_WIDTH-1:0] _TECHMAP_CONSTMSK_P_ = 0; generate if (AB_WIDTH == 0) begin - if (BUDGET < `LUT_WIDTH) - $__CMP2LCU #(.AB_WIDTH(AB_WIDTH), .AB_SIGNED(AB_SIGNED), .LCU_WIDTH(LCU_WIDTH+1), .BUDGET(`LUT_WIDTH), .CI(CI)) - _TECHMAP_REPLACE_ (.A(A), .B(B), .P({P, PP}), .G({G, GG}), .PP(1'b1), .GG(1'b0), .Y(Y)); - else begin - wire [LCU_WIDTH-1:0] CO; - $lcu #(.WIDTH(LCU_WIDTH)) _TECHMAP_REPLACE_ (.P(P), .G(G), .CI(CI), .CO(CO)); - assign Y = CO[LCU_WIDTH-1]; - end + wire [LCU_WIDTH-1:0] CO; + $lcu #(.WIDTH(LCU_WIDTH)) _TECHMAP_REPLACE_ (.P(P), .G(G), .CI(CI), .CO(CO)); + assign Y = CO[LCU_WIDTH-1]; end else begin - if (BUDGET < 2) + if (_TECHMAP_CONSTMSK_A_[AB_WIDTH-1:0] && _TECHMAP_CONSTMSK_B_[AB_WIDTH-1:0]) + localparam COST = 0; + else if (_TECHMAP_CONSTMSK_A_[AB_WIDTH-1:0] || _TECHMAP_CONSTMSK_B_[AB_WIDTH-1:0]) + localparam COST = 1; + else + localparam COST = 2; + + if (BUDGET < COST) $__CMP2LCU #(.AB_WIDTH(AB_WIDTH), .AB_SIGNED(AB_SIGNED), .LCU_WIDTH(LCU_WIDTH+1), .BUDGET(`LUT_WIDTH), .CI(CI)) - _TECHMAP_REPLACE_ (.A(A), .B(B), .P({P, PP}), .G({G, GG}), .PP(1'b1), .GG(1'b0), .Y(Y)); + _TECHMAP_REPLACE_ (.A(A), .B(B), .P({P, 1'b1}), .G({G, 1'b0}), .Y(Y)); else begin - wire PPP, GGG; + wire PP, GG; // Bit-wise equality (xnor) of A and B - assign PPP = A[AB_WIDTH-1] ^~ B[AB_WIDTH-1]; + assign PP = A[AB_WIDTH-1] ^~ B[AB_WIDTH-1]; if (AB_SIGNED) - assign GGG = ~A[AB_WIDTH-1] & B[AB_WIDTH-1]; - else if (BUDGET == `LUT_WIDTH) - assign GGG = A[AB_WIDTH-1] & ~B[AB_WIDTH-1]; + assign GG = ~A[AB_WIDTH-1] & B[AB_WIDTH-1]; + else if (_TECHMAP_CONSTMSK_P_[LCU_WIDTH-1]) // First compare for LUT if P (and G) is constant + assign GG = A[AB_WIDTH-1] & ~B[AB_WIDTH-1]; else // Priority "encoder" that checks A[i] == 1'b1 && B[i] == 1'b0 // from MSB down, deferring to less significant bits if the // MSBs are equal - assign GGG = PP & (A[AB_WIDTH-1] & ~B[AB_WIDTH-1]); - $__CMP2LCU #(.AB_WIDTH(AB_WIDTH-1), .AB_SIGNED(1'b0), .LCU_WIDTH(LCU_WIDTH), .BUDGET(BUDGET-2), .CI(CI)) - _TECHMAP_REPLACE_ (.A(A[AB_WIDTH-2:0]), .B(B[AB_WIDTH-2:0]), .P(P), .G(G), - // Propagate only if all bit pairs are equal + assign GG = P[0] & (A[AB_WIDTH-1] & ~B[AB_WIDTH-1]); + if (LCU_WIDTH == 1) begin + // Propagate only if all pairs are equal + // (inconclusive evidence to say A >= B) + wire P_ = P[0] & PP; + // Generate if any comparisons call for it + wire G_ = G[0] | GG; + end + else begin + // Propagate only if all pairs are equal // (inconclusive evidence to say A >= B) - .PP(PP & PPP), - // Generate if any bit pairs call for it - .GG(GG | GGG), - .Y(Y)); + wire [LCU_WIDTH-1:0] P_ = {P[LCU_WIDTH-1:1], P[0] & PP}; + // Generate if any comparisons call for it + wire [LCU_WIDTH-1:0] G_ = {G[LCU_WIDTH-1:1], G[0] | GG}; + end + $__CMP2LCU #(.AB_WIDTH(AB_WIDTH-1), .AB_SIGNED(1'b0), .LCU_WIDTH(LCU_WIDTH), .BUDGET(BUDGET-COST), .CI(CI)) + _TECHMAP_REPLACE_ (.A(A[AB_WIDTH-2:0]), .B(B[AB_WIDTH-2:0]), .P(P_), .G(G_), .Y(Y)); end end endgenerate -- cgit v1.2.3 From 051aefc3c259b69cf49ae97c7d57a71dcf37a844 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 20 Jan 2020 17:05:49 -0800 Subject: synth_xilinx: techmap +/cmp2lut.v and +/cmp2lcu.v in 'coarse' --- techlibs/xilinx/synth_xilinx.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'techlibs') diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 8553efd6b..ac4f5bcf4 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -393,8 +393,6 @@ struct SynthXilinxPass : public ScriptPass run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); run("clean", " (skip if '-nosrl' and '-widemux=0')"); } - - run("techmap -map +/cmp2lut.v -D LUT_WIDTH=" + lut_size_s); } if (check_label("map_dsp", "(skip if '-nodsp')")) { @@ -460,6 +458,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("coarse")) { + run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=" + lut_size_s); run("alumacc"); run("share"); run("opt"); -- cgit v1.2.3 From 2bf03c6ae0c4f03a4661c5878335b3115b57500c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Jan 2020 09:14:03 -0800 Subject: Cleanup +/cmp2lut.v --- techlibs/common/cmp2lut.v | 8 -------- 1 file changed, 8 deletions(-) (limited to 'techlibs') diff --git a/techlibs/common/cmp2lut.v b/techlibs/common/cmp2lut.v index 2f1bfd901..8ecd356cc 100644 --- a/techlibs/common/cmp2lut.v +++ b/techlibs/common/cmp2lut.v @@ -57,10 +57,6 @@ function automatic [(1 << `LUT_WIDTH)-1:0] gen_lut; o_bit = (lhs > rhs); if (operation == 3) o_bit = (lhs >= rhs); -// if (operation == 4) -// o_bit = (lhs == rhs); -// if (operation == 5) -// o_bit = (lhs != rhs); gen_lut = gen_lut | (o_bit << n); end end @@ -75,10 +71,6 @@ generate localparam operation = 2; if (_TECHMAP_CELLTYPE_ == "$ge") localparam operation = 3; -// if (_TECHMAP_CELLTYPE_ == "$eq") -// localparam operation = 4; -// if (_TECHMAP_CELLTYPE_ == "$ne") -// localparam operation = 5; if (A_WIDTH > `LUT_WIDTH || B_WIDTH > `LUT_WIDTH || Y_WIDTH != 1) wire _TECHMAP_FAIL_ = 1; -- cgit v1.2.3 From 5b87720b16d957765cd26a85633722dc882c24f9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Feb 2020 14:31:51 -0800 Subject: synth: use +/cmp2lcu.v in generic 'synth' too --- techlibs/common/synth.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'techlibs') diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index e7a192c07..513702357 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -225,9 +225,9 @@ struct SynthPass : public ScriptPass run("peepopt"); run("opt_clean"); if (help_mode) - run("techmap -map +/cmp2lut.v", " (if -lut)"); + run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v", " (if -lut)"); else - run(stringf("techmap -map +/cmp2lut.v -D LUT_WIDTH=%d", lut)); + run(stringf("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=%d", lut)); if (!noalumacc) run("alumacc", " (unless -noalumacc)"); if (!noshare) -- cgit v1.2.3 From 34c9b83854a09bb90e8b880774b58d91d7ed8ae7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Feb 2020 08:46:11 -0800 Subject: synth: only techmap cmp2{lut,lcu} if -lut --- techlibs/common/synth.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'techlibs') diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 513702357..d6dffdd7f 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -226,7 +226,7 @@ struct SynthPass : public ScriptPass run("opt_clean"); if (help_mode) run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v", " (if -lut)"); - else + else if (lut) run(stringf("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=%d", lut)); if (!noalumacc) run("alumacc", " (unless -noalumacc)"); -- cgit v1.2.3 From 7b09a20c0cc737c3d108c9e981f5989d2ba1423c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Feb 2020 08:46:38 -0800 Subject: cmp2lcu: fail if `LUT_WIDTH < 2 --- techlibs/common/cmp2lcu.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'techlibs') diff --git a/techlibs/common/cmp2lcu.v b/techlibs/common/cmp2lcu.v index b302d592f..b4fadaaad 100644 --- a/techlibs/common/cmp2lcu.v +++ b/techlibs/common/cmp2lcu.v @@ -19,7 +19,7 @@ output [Y_WIDTH-1:0] Y; parameter _TECHMAP_CELLTYPE_ = ""; generate - if (_TECHMAP_CELLTYPE_ == "") + if (_TECHMAP_CELLTYPE_ == "" || `LUT_WIDTH < 2) wire _TECHMAP_FAIL_ = 1; else if (_TECHMAP_CELLTYPE_ == "$lt") begin // Transform $lt into $gt by swapping A and B -- cgit v1.2.3 From 7b38cde2df0631aac0377cd155653ae0e0084ed0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 3 Apr 2020 14:25:04 -0700 Subject: cmp2lcu: rename _90_lcu_cmp -> _80_lcu_cmp --- techlibs/common/cmp2lcu.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'techlibs') diff --git a/techlibs/common/cmp2lcu.v b/techlibs/common/cmp2lcu.v index b4fadaaad..b6f4aeed6 100644 --- a/techlibs/common/cmp2lcu.v +++ b/techlibs/common/cmp2lcu.v @@ -4,7 +4,7 @@ // which is typically mapped to dedicated (and fast) FPGA // carry-chains. (* techmap_celltype = "$lt $le $gt $ge" *) -module _90_lcu_cmp_ (A, B, Y); +module _80_lcu_cmp_ (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; -- cgit v1.2.3