Added $lcu cell type
[yosys.git] / techlibs / common / techmap.v
index c0645267d609630074747a8c3b22337dde2cd206..491511dbc94582acebbad11916c036254cc8f02f 100644 (file)
 // Use simplemap for trivial cell types
 // --------------------------------------------------------
 
-(* techmap_simplemap *)
-(* techmap_celltype = "$pos $bu0" *)
-module simplemap_buffers;
-endmodule
-
 (* techmap_simplemap *)
 (* techmap_celltype = "$not $and $or $xor $xnor" *)
 module simplemap_bool_ops;
@@ -59,7 +54,7 @@ module simplemap_logic_ops;
 endmodule
 
 (* techmap_simplemap *)
-(* techmap_celltype = "$slice $concat $mux" *)
+(* techmap_celltype = "$pos $slice $concat $mux" *)
 module simplemap_various;
 endmodule
 
@@ -251,40 +246,19 @@ endmodule
 // ALU Infrastructure
 // --------------------------------------------------------
 
-module \$__alu_ripple (A, B, CI, X, Y, CO);
+module \$fa (A, B, C, X, Y);
        parameter WIDTH = 1;
 
-       input [WIDTH-1:0] A, B;
+       input [WIDTH-1:0] A, B, C;
        output [WIDTH-1:0] X, Y;
 
-       input CI;
-       output [WIDTH-1:0] CO;
-
-       wire [WIDTH:0] carry;
-       assign carry[0] = CI;
-       assign CO = carry[WIDTH:1];
+       wire [WIDTH-1:0] t1, t2, t3;
 
-       genvar i;
-       generate
-               for (i = 0; i < WIDTH; i = i+1)
-               begin:V
-                       // {x, y} = a + b + c
-                       wire a, b, c, x, y;
-                       wire t1, t2, t3;
-
-                       \$_AND_ gate1 ( .A(a),  .B(b),  .Y(t1) );
-                       \$_XOR_ gate2 ( .A(a),  .B(b),  .Y(t2) );
-                       \$_AND_ gate3 ( .A(t2), .B(c),  .Y(t3) ); 
-                       \$_XOR_ gate4 ( .A(t2), .B(c),  .Y(y)  );
-                       \$_OR_  gate5 ( .A(t1), .B(t3), .Y(x)  );
-
-                       assign a = A[i], b = B[i], c = carry[i];
-                       assign carry[i+1] = x, X[i] = t2, Y[i] = y;
-               end
-       endgenerate
+       assign t1 = A ^ B, t2 = A & B, t3 = C & t1;
+       assign Y = t1 ^ C, X = t2 | t3;
 endmodule
 
-module \$__lcu (P, G, CI, CO);
+module \$lcu (P, G, CI, CO);
        parameter WIDTH = 2;
 
        input [WIDTH-1:0] P, G;
@@ -328,37 +302,6 @@ module \$__lcu (P, G, CI, CO);
        assign CO = g;
 endmodule
 
-module \$__alu_lookahead (A, B, CI, X, Y, CO);
-       parameter WIDTH = 1;
-
-       input [WIDTH-1:0] A, B;
-       output [WIDTH-1:0] X, Y;
-
-       input CI;
-       output [WIDTH-1:0] CO;
-
-       wire [WIDTH-1:0] P, G;
-       wire [WIDTH:0] carry;
-
-       genvar i;
-       generate
-               for (i = 0; i < WIDTH; i = i+1)
-               begin:V
-                       wire a, b, c, p, g, y;
-
-                       \$_AND_ gate1 ( .A(a),  .B(b),  .Y(g) );
-                       \$_XOR_ gate2 ( .A(a),  .B(b),  .Y(p) );
-                       \$_XOR_ gate3 ( .A(p),  .B(c),  .Y(y) );
-
-                       assign a = A[i], b = B[i], c = carry[i];
-                       assign P[i] = p, G[i] = g, X[i] = p, Y[i] = y;
-               end
-       endgenerate
-
-       \$__lcu #(.WIDTH(WIDTH)) lcu (.P(P), .G(G), .CI(CI), .CO(CO));
-       assign carry = {CO, CI};
-endmodule
-
 module \$alu (A, B, CI, BI, X, Y, CO);
        parameter A_SIGNED = 0;
        parameter B_SIGNED = 0;
@@ -377,15 +320,13 @@ module \$alu (A, B, CI, BI, X, Y, CO);
        \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
        \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
 
-`ifdef ALU_RIPPLE
-       \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO));
-`else
-       if (Y_WIDTH <= 4) begin
-               \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO));
-       end else begin
-               \$__alu_lookahead #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO));
-       end
-`endif
+       wire [Y_WIDTH-1:0] AA = A_buf;
+       wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
+
+       \$lcu #(.WIDTH(Y_WIDTH)) lcu (.P(X), .G(AA & BB), .CI(CI), .CO(CO));
+
+       assign X = AA ^ BB;
+       assign Y = X ^ {CO, CI};
 endmodule
 
 
@@ -460,102 +401,8 @@ endmodule
 // Multiply
 // --------------------------------------------------------
 
-module \$__acc_set (acc_new, value);
-       parameter WIDTH = 1;
-       output reg [2*WIDTH-1:0] acc_new;
-       input [WIDTH-1:0] value;
-
-       wire [1023:0] _TECHMAP_DO_ = "proc;;;";
-
-       integer k;
-       always @* begin
-               for (k = 0; k < WIDTH; k = k+1) begin
-                       acc_new[2*k +: 2] = value[k];
-               end
-       end
-endmodule
-
-module \$__acc_add (acc_new, acc_old, value);
-       parameter WIDTH = 1;
-       output reg [2*WIDTH-1:0] acc_new;
-       input [2*WIDTH-1:0] acc_old;
-       input [WIDTH-1:0] value;
-
-       wire [1023:0] _TECHMAP_DO_ = "proc; simplemap; opt -purge";
-
-       integer k;
-       reg a, b, c;
-
-       always @* begin
-               for (k = 0; k < WIDTH; k = k+1) begin
-                       a = acc_old[2*k];
-                       b = k ? acc_old[2*k-1] : 1'b0;
-                       c = value[k];
-                       acc_new[2*k] = (a ^ b) ^ c;
-                       acc_new[2*k+1] = (a & b) | ((a ^ b) & c);
-               end
-       end
-endmodule
-
-module \$__acc_get (value, acc);
-       parameter WIDTH = 1;
-       output reg [WIDTH-1:0] value;
-       input [2*WIDTH-1:0] acc;
-
-       wire [1023:0] _TECHMAP_DO_ = "proc;;;";
-
-       integer k;
-
-       always @* begin
-               // at the end of the multiplier chain the carry-save accumulator
-               // should also have propagated all carries. thus we just need to
-               // copy the even bits from the carry accumulator to the output.
-               for (k = 0; k < WIDTH; k = k+1) begin
-                       value[k] = acc[2*k];
-               end
-       end
-endmodule
-
-module \$__acc_mul (A, B, Y);
-       parameter WIDTH = 1;
-       input [WIDTH-1:0] A, B;
-       output [WIDTH-1:0] Y;
-
-       wire [1023:0] _TECHMAP_DO_ = "proc;;";
-
-       integer i;
-       reg [WIDTH-1:0] x;
-       reg [2*WIDTH-1:0] y;
-
-       (* via_celltype = "\\$__acc_set acc_new" *)
-       (* via_celltype_defparam_WIDTH = WIDTH *)
-       function [2*WIDTH-1:0] acc_set;
-               input [WIDTH-1:0] value;
-       endfunction
-
-       (* via_celltype = "\\$__acc_add acc_new" *)
-       (* via_celltype_defparam_WIDTH = WIDTH *)
-       function [2*WIDTH-1:0] acc_add;
-               input [2*WIDTH-1:0] acc_old;
-               input [WIDTH-1:0] value;
-       endfunction
-
-       (* via_celltype = "\\$__acc_get value" *)
-       (* via_celltype_defparam_WIDTH = WIDTH *)
-       function [WIDTH-1:0] acc_get;
-               input [2*WIDTH-1:0] acc;
-       endfunction
-
-       always @* begin
-               x = B;
-               y = acc_set(A[0] ? x : 1'b0);
-               for (i = 1; i < WIDTH; i = i+1) begin
-                       x = {x[WIDTH-2:0], 1'b0};
-                       y = acc_add(y, A[i] ? x : 1'b0);
-               end
-       end
-
-       assign Y = acc_get(y);
+(* techmap_maccmap *)
+module \$macc ;
 endmodule
 
 module \$mul (A, B, Y);
@@ -571,15 +418,21 @@ module \$mul (A, B, Y);
 
        wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt -purge";
 
-       wire [Y_WIDTH-1:0] A_buf, B_buf;
-       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
-       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
-
-       \$__acc_mul #(
-               .WIDTH(Y_WIDTH)
+       localparam [ 3:0] CONFIG_WIDTH_BITS = 15;
+       localparam [ 0:0] CONFIG_IS_SIGNED = A_SIGNED && B_SIGNED;
+       localparam [ 0:0] CONFIG_DO_SUBTRACT = 0;
+       localparam [14:0] CONFIG_A_WIDTH = A_WIDTH;
+       localparam [14:0] CONFIG_B_WIDTH = B_WIDTH;
+
+       \$macc #(
+               .CONFIG({CONFIG_B_WIDTH, CONFIG_A_WIDTH, CONFIG_DO_SUBTRACT, CONFIG_IS_SIGNED, CONFIG_WIDTH_BITS}),
+               .CONFIG_WIDTH(15 + 15 + 2 + 4),
+               .A_WIDTH(B_WIDTH + A_WIDTH),
+               .B_WIDTH(0),
+               .Y_WIDTH(Y_WIDTH)
        ) _TECHMAP_REPLACE_ (
-               .A(A_buf),
-               .B(B_buf),
+               .A({B, A}),
+               .B(),
                .Y(Y)
        );
 endmodule
@@ -738,8 +591,8 @@ module \$eq (A, B, Y);
 
        wire carry, carry_sign;
        wire [WIDTH-1:0] A_buf, B_buf;
-       \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
-       \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
+       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
+       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
 
        assign Y = ~|(A_buf ^ B_buf);
 endmodule
@@ -759,8 +612,8 @@ module \$ne (A, B, Y);
 
        wire carry, carry_sign;
        wire [WIDTH-1:0] A_buf, B_buf;
-       \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
-       \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
+       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
+       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
 
        assign Y = |(A_buf ^ B_buf);
 endmodule