diff options
| author | Eddie Hung <eddie@fpgeh.com> | 2019-08-13 10:21:24 -0700 | 
|---|---|---|
| committer | Eddie Hung <eddie@fpgeh.com> | 2019-08-13 10:21:24 -0700 | 
| commit | 2a1b98d478918b0a17c7e509ada6e7a71bbab526 (patch) | |
| tree | 08db51f86e8ee1ebac897e7fb4a4e23ee1503f6f /techlibs/common | |
| parent | f890cfb63b71ae7b09e19c290ec70c358dcbe9cd (diff) | |
| download | yosys-2a1b98d478918b0a17c7e509ada6e7a71bbab526.tar.gz yosys-2a1b98d478918b0a17c7e509ada6e7a71bbab526.tar.bz2 yosys-2a1b98d478918b0a17c7e509ada6e7a71bbab526.zip | |
Add DSP_A_MAXWIDTH_PARTIAL, refactor
Diffstat (limited to 'techlibs/common')
| -rw-r--r-- | techlibs/common/mul2dsp.v | 254 | 
1 files changed, 110 insertions, 144 deletions
| diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 8e37201e2..71d5a5454 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -27,20 +27,30 @@   */
  `ifndef DSP_A_MAXWIDTH
 -$error("Macro DSP_A_MAXWIDTH must be defined");
 +$fatal(1, "Macro DSP_A_MAXWIDTH must be defined");
  `endif
  `ifndef DSP_B_MAXWIDTH
 -$error("Macro DSP_B_MAXWIDTH must be defined");
 +$fatal(1, "Macro DSP_B_MAXWIDTH must be defined");
 +`endif
 +`ifndef DSP_B_MAXWIDTH
 +$fatal(1, "Macro DSP_B_MAXWIDTH must be defined");
 +`endif
 +`ifndef DSP_A_MAXWIDTH_PARTIAL
 +`define DSP_A_MAXWIDTH_PARTIAL `DSP_A_MAXWIDTH
 +`endif
 +`ifndef DSP_B_MAXWIDTH_PARTIAL
 +`define DSP_B_MAXWIDTH_PARTIAL `DSP_B_MAXWIDTH
  `endif
  `ifndef DSP_NAME
 -$error("Macro DSP_NAME must be defined");
 +$fatal(1, "Macro DSP_NAME must be defined");
  `endif
  `define MAX(a,b) (a > b ? a : b)
  `define MIN(a,b) (a < b ? a : b)
 -module \$mul (A, B, Y); 
 +(* techmap_celltype = "$mul $__mul" *)
 +module _80_mul (A, B, Y);
  	parameter A_SIGNED = 0;
  	parameter B_SIGNED = 0;
  	parameter A_WIDTH = 1;
 @@ -51,12 +61,26 @@ module \$mul (A, B, Y);  	input [B_WIDTH-1:0] B;
  	output [Y_WIDTH-1:0] Y;
 +	parameter _TECHMAP_CELLTYPE_ = "";
 +
  	generate
 -	if (A_SIGNED != B_SIGNED)
 +	if (0) begin end
 +`ifdef DSP_A_MINWIDTH
 +	else if (A_WIDTH < `DSP_A_MINWIDTH)
 +		wire _TECHMAP_FAIL_ = 1;
 +`endif
 +`ifdef DSP_B_MINWIDTH
 +	else if (B_WIDTH < `DSP_B_MINWIDTH)
 +		wire _TECHMAP_FAIL_ = 1;
 +`endif
 +`ifdef DSP_Y_MINWIDTH
 +	else if (Y_WIDTH < `DSP_Y_MINWIDTH)
 +		wire _TECHMAP_FAIL_ = 1;
 +`endif
 +	else if (_TECHMAP_CELLTYPE_ == "$mul" && A_SIGNED != B_SIGNED)
  		wire _TECHMAP_FAIL_ = 1;
 -	// NB: A_SIGNED == B_SIGNED from here
  `ifdef DSP_SIGNEDONLY
 -	else if (!A_SIGNED)
 +	else if (_TECHMAP_CELLTYPE_ == "$mul" && !A_SIGNED)
  		\$mul #(
  			.A_SIGNED(1),
  			.B_SIGNED(1),
 @@ -81,102 +105,53 @@ module \$mul (A, B, Y);  			.B(A),
  			.Y(Y)
  		);
 -	else
 -		\$__mul #(
 -			.A_SIGNED(A_SIGNED),
 -			.B_SIGNED(B_SIGNED),
 -			.A_WIDTH(A_WIDTH),
 -			.B_WIDTH(B_WIDTH),
 -			.Y_WIDTH(Y_WIDTH)
 -		) _TECHMAP_REPLACE_ (
 -			.A(A),
 -			.B(B),
 -			.Y(Y)
 -		);
 -	endgenerate
 -endmodule
 -
 -module \$__mul (A, B, Y);
 -	parameter A_SIGNED = 0;
 -	parameter B_SIGNED = 0;
 -	parameter A_WIDTH = 1;
 -	parameter B_WIDTH = 1;
 -	parameter Y_WIDTH = 1;
 -
 -	input [A_WIDTH-1:0] A;
 -	input [B_WIDTH-1:0] B;
 -	output [Y_WIDTH-1:0] Y;
 -
 -	wire [1023:0] _TECHMAP_DO_ = "proc; clean";
 +	else begin
 +		wire [1023:0] _TECHMAP_DO_ = "proc; clean";
  `ifdef DSP_SIGNEDONLY
 -	localparam sign_headroom = 1;
 +		localparam sign_headroom = 1;
  `else
 -	localparam sign_headroom = 0;
 +		localparam sign_headroom = 0;
  `endif
 -	genvar i;
 -	generate
 -        if (0) begin end
 -`ifdef DSP_A_MINWIDTH
 -		else if (A_WIDTH < `DSP_A_MINWIDTH)
 -			wire _TECHMAP_FAIL_ = 1;
 -`endif
 -`ifdef DSP_B_MINWIDTH
 -		else if (B_WIDTH < `DSP_B_MINWIDTH)
 -			wire _TECHMAP_FAIL_ = 1;
 -`endif
 -`ifdef DSP_Y_MINWIDTH
 -		else if (Y_WIDTH < `DSP_Y_MINWIDTH)
 -			wire _TECHMAP_FAIL_ = 1;
 -`endif
 -		else if (A_WIDTH > `DSP_A_MAXWIDTH) begin
 -			localparam n = (A_WIDTH+`DSP_A_MAXWIDTH-sign_headroom-1) / (`DSP_A_MAXWIDTH-sign_headroom);
 -			localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH);
 -			localparam last_Y_WIDTH = `MIN(partial_Y_WIDTH, B_WIDTH+A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom));
 +		genvar i;
 +		if (A_WIDTH > `DSP_A_MAXWIDTH) begin
 +			localparam n = (A_WIDTH-`DSP_A_MAXWIDTH+`DSP_A_MAXWIDTH_PARTIAL-sign_headroom-1) / (`DSP_A_MAXWIDTH_PARTIAL-sign_headroom);
 +			localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH_PARTIAL);
 +			localparam last_A_WIDTH = A_WIDTH-n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom);
 +			localparam last_Y_WIDTH = B_WIDTH+last_A_WIDTH;
  			if (A_SIGNED && B_SIGNED) begin
 -				wire signed [partial_Y_WIDTH-1:0] partial [n-2:0];
 +				wire signed [partial_Y_WIDTH-1:0] partial [n-1:0];
  				wire signed [last_Y_WIDTH-1:0] last_partial;
 -				wire signed [Y_WIDTH-1:0] partial_sum [n-1:0];
 +				wire signed [Y_WIDTH-1:0] partial_sum [n:0];
  			end
  			else begin
  				wire [partial_Y_WIDTH-1:0] partial [n-1:0];
  				wire [last_Y_WIDTH-1:0] last_partial;
 -				wire [Y_WIDTH-1:0] partial_sum [n-1:0];
 +				wire [Y_WIDTH-1:0] partial_sum [n:0];
  			end
 -			\$__mul #(
 -				.A_SIGNED(sign_headroom),
 -				.B_SIGNED(B_SIGNED),
 -				.A_WIDTH(`DSP_A_MAXWIDTH),
 -				.B_WIDTH(B_WIDTH),
 -				.Y_WIDTH(partial_Y_WIDTH)
 -			) mul_slice_first (
 -				.A({{sign_headroom{1'b0}}, A[`DSP_A_MAXWIDTH-sign_headroom-1 : 0]}),
 -				.B(B),
 -				.Y(partial[0])
 -			);
 -			assign partial_sum[0] = partial[0];
 -
 -			for (i = 1; i < n-1; i=i+1) begin:slice
 +			for (i = 0; i < n; i=i+1) begin:slice
  				\$__mul #(
  					.A_SIGNED(sign_headroom),
  					.B_SIGNED(B_SIGNED),
 -					.A_WIDTH(`DSP_A_MAXWIDTH),
 +					.A_WIDTH(`DSP_A_MAXWIDTH_PARTIAL),
  					.B_WIDTH(B_WIDTH),
  					.Y_WIDTH(partial_Y_WIDTH)
  				) mul_slice (
 -					.A({{sign_headroom{1'b0}}, A[i*(`DSP_A_MAXWIDTH-sign_headroom) +: `DSP_A_MAXWIDTH-sign_headroom]}),
 +					.A({{sign_headroom{1'b0}}, A[i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_A_MAXWIDTH_PARTIAL-sign_headroom]}),
  					.B(B),
  					.Y(partial[i])
  				);
  				// TODO: Currently a 'cascade' approach to summing the partial
  				//       products is taken here, but a more efficient 'binary
  				//       reduction' approach also exists...
 -				assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[i-1];
 +				if (i == 0)
 +					assign partial_sum[i] = partial[i];
 +				else
 +					assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1];
  			end
 -			localparam last_A_WIDTH = A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom);
  			\$__mul #(
  				.A_SIGNED(A_SIGNED),
  				.B_SIGNED(B_SIGNED),
 @@ -188,56 +163,46 @@ module \$__mul (A, B, Y);  				.B(B),
  				.Y(last_partial)
  			);
 -			assign partial_sum[n-1] = (last_partial << (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[n-2];
 -			assign Y = partial_sum[n-1];
 +			assign partial_sum[n] = (last_partial << n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1];
 +			assign Y = partial_sum[n];
  		end
  		else if (B_WIDTH > `DSP_B_MAXWIDTH) begin
 -			localparam n = (B_WIDTH+`DSP_B_MAXWIDTH-sign_headroom-1) / (`DSP_B_MAXWIDTH-sign_headroom);
 -			localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH);
 -			localparam last_Y_WIDTH = `MIN(partial_Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH-sign_headroom));
 +			localparam n = (B_WIDTH-`DSP_B_MAXWIDTH+`DSP_B_MAXWIDTH_PARTIAL-sign_headroom-1) / (`DSP_B_MAXWIDTH_PARTIAL-sign_headroom);
 +			localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH_PARTIAL);
 +			localparam last_B_WIDTH = B_WIDTH-n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom);
 +			localparam last_Y_WIDTH = A_WIDTH+last_B_WIDTH;
  			if (A_SIGNED && B_SIGNED) begin
 -				wire signed [partial_Y_WIDTH-1:0] partial [n-2:0];
 +				wire signed [partial_Y_WIDTH-1:0] partial [n-1:0];
  				wire signed [last_Y_WIDTH-1:0] last_partial;
 -				wire signed [Y_WIDTH-1:0] partial_sum [n-1:0];
 +				wire signed [Y_WIDTH-1:0] partial_sum [n:0];
  			end
  			else begin
  				wire [partial_Y_WIDTH-1:0] partial [n-1:0];
  				wire [last_Y_WIDTH-1:0] last_partial;
 -				wire [Y_WIDTH-1:0] partial_sum [n-1:0];
 +				wire [Y_WIDTH-1:0] partial_sum [n:0];
  			end
 -			\$__mul #(
 -				.A_SIGNED(A_SIGNED),
 -				.B_SIGNED(sign_headroom),
 -				.A_WIDTH(A_WIDTH),
 -				.B_WIDTH(`DSP_B_MAXWIDTH),
 -				.Y_WIDTH(partial_Y_WIDTH)
 -			) mul_first (
 -				.A(A),
 -				.B({{sign_headroom{1'b0}}, B[`DSP_B_MAXWIDTH-sign_headroom-1 : 0]}),
 -				.Y(partial[0])
 -			);
 -			assign partial_sum[0] = partial[0];
 -
 -			for (i = 1; i < n-1; i=i+1) begin:slice
 +			for (i = 0; i < n; i=i+1) begin:slice
  				\$__mul #(
  					.A_SIGNED(A_SIGNED),
  					.B_SIGNED(sign_headroom),
  					.A_WIDTH(A_WIDTH),
 -					.B_WIDTH(`DSP_B_MAXWIDTH),
 +					.B_WIDTH(`DSP_B_MAXWIDTH_PARTIAL),
  					.Y_WIDTH(partial_Y_WIDTH)
  				) mul (
  					.A(A),
 -					.B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH-sign_headroom) +: `DSP_B_MAXWIDTH-sign_headroom]}),
 +					.B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_B_MAXWIDTH_PARTIAL-sign_headroom]}),
  					.Y(partial[i])
  				);
 -				// TODO: Currently a 'cascade' approach to summing the partial 
 +				// TODO: Currently a 'cascade' approach to summing the partial
  				//       products is taken here, but a more efficient 'binary
  				//       reduction' approach also exists...
 -				assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[i-1];
 +				if (i == 0)
 +					assign partial_sum[i] = partial[i];
 +				else
 +					assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1];
  			end
 -			localparam last_B_WIDTH = B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH-sign_headroom);
  			\$__mul #(
  				.A_SIGNED(A_SIGNED),
  				.B_SIGNED(B_SIGNED),
 @@ -249,10 +214,10 @@ module \$__mul (A, B, Y);  				.B(B[B_WIDTH-1 -: last_B_WIDTH]),
  				.Y(last_partial)
  			);
 -			assign partial_sum[n-1] = (last_partial << (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[n-2];
 -			assign Y = partial_sum[n-1];
 +			assign partial_sum[n] = (last_partial << n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1];
 +			assign Y = partial_sum[n];
  		end
 -		else begin 
 +		else begin
  			if (A_SIGNED)
  				wire signed [`DSP_A_MAXWIDTH-1:0] Aext = $signed(A);
  			else
 @@ -274,11 +239,12 @@ module \$__mul (A, B, Y);  				.Y(Y)
  			);
  		end
 +	end
  	endgenerate
  endmodule
 -(* techmap_celltype = "$__mul" *)
 -module $__soft_mul (A, B, Y); 
 +(* techmap_celltype = "$mul $__mul" *)
 +module _90_soft_mul (A, B, Y);
  	parameter A_SIGNED = 0;
  	parameter B_SIGNED = 0;
  	parameter A_WIDTH = 1;
 @@ -292,41 +258,41 @@ module $__soft_mul (A, B, Y);  	// Indirection necessary since mapping
  	//   back to $mul will cause recursion
  	generate
 -		if (A_SIGNED && !B_SIGNED)
 -			\$__soft__mul #(
 -				.A_SIGNED(A_SIGNED),
 -				.B_SIGNED(1),
 -				.A_WIDTH(A_WIDTH),
 -				.B_WIDTH(B_WIDTH+1),
 -				.Y_WIDTH(Y_WIDTH)
 -			) _TECHMAP_REPLACE_ (
 -				.A(A),
 -				.B({1'b0,B}),
 -				.Y(Y)
 -			);
 -		else if (!A_SIGNED && B_SIGNED)
 -			\$__soft_mul #(
 -				.A_SIGNED(1),
 -				.B_SIGNED(B_SIGNED),
 -				.A_WIDTH(A_WIDTH+1),
 -				.B_WIDTH(B_WIDTH),
 -				.Y_WIDTH(Y_WIDTH)
 -			) _TECHMAP_REPLACE_ (
 -				.A({1'b0,A}),
 -				.B(B),
 -				.Y(Y)
 -			);
 -		else
 -			\$__soft_mul #(
 -				.A_SIGNED(A_SIGNED),
 -				.B_SIGNED(B_SIGNED),
 -				.A_WIDTH(A_WIDTH),
 -				.B_WIDTH(B_WIDTH),
 -				.Y_WIDTH(Y_WIDTH)
 -			) _TECHMAP_REPLACE_ (
 -				.A(A),
 -				.B(B),
 -				.Y(Y)
 -			);
 +	if (A_SIGNED && !B_SIGNED)
 +		\$__soft_mul #(
 +			.A_SIGNED(A_SIGNED),
 +			.B_SIGNED(1),
 +			.A_WIDTH(A_WIDTH),
 +			.B_WIDTH(B_WIDTH+1),
 +			.Y_WIDTH(Y_WIDTH)
 +		) _TECHMAP_REPLACE_ (
 +			.A(A),
 +			.B({1'b0,B}),
 +			.Y(Y)
 +		);
 +	else if (!A_SIGNED && B_SIGNED)
 +		\$__soft_mul #(
 +			.A_SIGNED(1),
 +			.B_SIGNED(B_SIGNED),
 +			.A_WIDTH(A_WIDTH+1),
 +			.B_WIDTH(B_WIDTH),
 +			.Y_WIDTH(Y_WIDTH)
 +		) _TECHMAP_REPLACE_ (
 +			.A({1'b0,A}),
 +			.B(B),
 +			.Y(Y)
 +		);
 +	else
 +		\$__soft_mul #(
 +			.A_SIGNED(A_SIGNED),
 +			.B_SIGNED(B_SIGNED),
 +			.A_WIDTH(A_WIDTH),
 +			.B_WIDTH(B_WIDTH),
 +			.Y_WIDTH(Y_WIDTH)
 +		) _TECHMAP_REPLACE_ (
 +			.A(A),
 +			.B(B),
 +			.Y(Y)
 +		);
  	endgenerate
  endmodule
 | 
