aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs
diff options
context:
space:
mode:
authorEddie Hung <eddie@fpgeh.com>2020-01-17 10:51:27 -0800
committerEddie Hung <eddie@fpgeh.com>2020-04-03 14:28:22 -0700
commit9b6370067858aa37825e7a030cd204726f0b58f9 (patch)
tree4617b57873d6c2bebe6a1333e794fd3a96cb7b1f /techlibs
parentfffe42d4c1dbfdf976ecb84e16a759552c8e2dd0 (diff)
downloadyosys-9b6370067858aa37825e7a030cd204726f0b58f9.tar.gz
yosys-9b6370067858aa37825e7a030cd204726f0b58f9.tar.bz2
yosys-9b6370067858aa37825e7a030cd204726f0b58f9.zip
techmap +/cmp2lcu.v for decomposing arithmetic compares to $lcu
Diffstat (limited to 'techlibs')
-rw-r--r--techlibs/common/Makefile.inc1
-rw-r--r--techlibs/common/cmp2lcu.v83
2 files changed, 84 insertions, 0 deletions
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